Swift语言中的错误处理 [英] Error-Handling in Swift-Language

查看:79
本文介绍了Swift语言中的错误处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我没有读过太多的Swift,但我注意到的一件事是没有例外。
那么他们如何在Swift中进行错误处理呢?有没有人发现任何与错误处理有关的东西?

解决方案

Swift 2&3


$ b $在Swift 2中,事情发生了一些变化,因为有一个新的错误处理机制,它与异常有些更相似,但是不同之处。



1。指示错误的可能性



如果函数/方法想要表明它可能会引发错误,它应该包含 throws 关键字像这样

  func summonDefaultDragon()throws  - > Dragon 

注意:功能实际上可以抛出的错误类型没有规定。该声明只是声明该函数可以抛出任何实现ErrorType类型的实例,或者根本就不会抛出。



2。调用函数可能会导致错误



为了调用函数,您需要使用try关键字,像这样

  try summonDefaultDragon()

catch块这样

  do {
let dragon = try summonDefaultDragon()
} catch DragonError.dragonIsMissing {
//某些特定情况下的错误处理
}捕获DragonError.notEnoughMana(让manaRequired){
//其他具体案例error-handlng
} catch {
//捕获所有错误处理
}

注意:catch子句使用Swift模式匹配的所有强大功能,因此您在这里非常灵活。



您可以决定传播错误,如果您正在调用投掷函数从一个本身标记为的函数throws 关键字:

  func (任务:任务)抛出{
让龙=尝试summonDefaultDragon()
quest.ride(龙)
}

或者,您可以使用 try调用投掷函数。

  let dragonOrNil =尝试? summonDefaultDragon()

这样你就可以得到返回值,否则返回null。使用这种方式你不会得到错误对象。



这意味着你也可以将 try?如下:

 如果让龙=尝试? summonDefaultDragon()

 守卫让龙=尝试? summonDefaultDragon()else {...} 

最后,你可以决定你知道错误不会实际发生(例如因为您已经检查是先决条件),并使用 try!关键字:

 code>让龙=尝试! summonDefaultDragon()

如果函数实际引发错误,那么您将在申请和申请将终止。



3。抛出错误



为了抛出一个错误,您使用这样的throw关键字

  throw DragonError.dragonIsMissing 

你可以抛出符合 ErrorType 协议。对于初学者 NSError 符合此协议,但您可能希望使用基于枚举的 ErrorType ,使您能够组合多个相关的错误,可能有额外的数据片段,像这样

 枚举DragonError:ErrorType {
case dragonIsMissing
case notEnoughMana(requiredMana:Int)
...
}






新的Swift 2& 3错误机制和Java / C#/ C ++风格异常如下:




  • 语法有点不同: do- catch + try + defer vs traditional try-catch-最终语法。

  • 异常处理通常在异常路径中比在成功路径中导致更高的执行时间。在这种情况下,Swift 2.0错误并不是这样,其中成功路径和错误路径的成本大致相同。

  • 必须声明所有错误投掷代码,而异常可能会从任何地方抛出。所有错误都是Java命名中的检查异常。但是,与Java不同,您不会指定潜在的抛出错误。

  • Swift异常与ObjC异常不兼容。您的 do-catch 块不会捕获任何NSException,反之亦然,因为您必须使用ObjC。

  • Swift异常兼容与Cocoa NSError 方法约定返回 false (对于 Bool 返回函数)或 nil (for AnyObject 返回函数)并传递 NSErrorPointer 与错误详细信息。



作为一个额外的合成糖,以缓解错误处理,还有两个概念




  • 延期操作(使用 defer 关键字),让您实现与最终块相同的效果Java / C#/ etc

  • 保护语句(使用 guard 关键字),它允许您在/ else代码写入少于正常错误检查/信令代码。






Swift 1



运行时错误:



由于Leandros建议处理runtim e错误(如网络连接问题,解析数据,打开文件等),您应该像ObjC一样使用 NSError ,因为Foundation,AppKit,UIKit等报告他们这样的错误。所以它比语言的东西更框架的东西。



正在使用的另一个频繁模式是分隔符成功/失败块,如AFNetworking:

  var sessionManager = AFHTTPSessionManager(baseURL:NSURL(string:yavin4.yavin.planets))
sessionManager.HEAD(/ api / destoryDe​​athStar参数:xwingSquad,
success:{(NSURLSessionDataTask) - > Void in
println(Success)
},
failure:{(NSURLSessionDataTask,NSError)
println(失败)
})

仍然失败阻止频繁接收 NSError 实例,描述错误。



程序员错误: p>

对于程序员错误(像数组元素的边界访问,传递给函数调用的无效参数等),您在ObjC中使用了异常。 Swift语言似乎没有对异常的任何语言支持(例如 throw catch ,etc关键字)。但是,由于文档表明它在与ObjC相同的运行时运行,因此您仍然可以像这样抛出 NSExceptions

  NSException(name:SomeName,reason:SomeReason,userInfo:nil).raise()

尽管您可以选择在ObjC代码中捕获异常,但您只能在纯Swift中捕获它们。



问题是您是否应该为程序员错误抛出异常,或者使用苹果在语言指南中建议的断言。


I haven't read too much into Swift but one thing I noticed is that there are no exceptions. So how do they do error handling in Swift? Has anyone found anything related to error-handling?

解决方案

Swift 2 & 3

Things have changed a bit in Swift 2, as there is a new error-handling mechanism, that is somewhat more similar to exceptions but different in detail.

1. Indicating error possibility

If function/method wants to indicate that it may throw an error, it should contain throws keyword like this

func summonDefaultDragon() throws -> Dragon

Note: there is no specification for type of error the function actually can throw. This declaration simply states that the function can throw an instance of any type implementing ErrorType or is not throwing at all.

2. Invoking function that may throw errors

In order to invoke function you need to use try keyword, like this

try summonDefaultDragon()

this line should normally be present do-catch block like this

do {
    let dragon = try summonDefaultDragon() 
} catch DragonError.dragonIsMissing {
    // Some specific-case error-handling
} catch DragonError.notEnoughMana(let manaRequired) {
    // Other specific-case error-handlng
} catch {
    // Catch all error-handling
}

Note: catch clause use all the powerful features of Swift pattern matching so you are very flexible here.

You may decided to propagate the error, if your are calling a throwing function from a function that is itself marked with throws keyword:

func fulfill(quest: Quest) throws {
    let dragon = try summonDefaultDragon()
    quest.ride(dragon)
} 

Alternatively, you can call throwing function using try?:

let dragonOrNil = try? summonDefaultDragon()

This way you either get the return value or nil, if any error occurred. Using this way you do not get the error object.

Which means that you can also combine try? with useful statements like:

if let dragon = try? summonDefaultDragon()

or

guard let dragon = try? summonDefaultDragon() else { ... }

Finally, you can decide that you know that error will not actually occur (e.g. because you have already checked are prerequisites) and use try! keyword:

let dragon = try! summonDefaultDragon()

If the function actually throws an error, then you'll get a runtime error in your application and the application will terminate.

3. Throwing an error

In order to throw an error you use throw keyword like this

throw DragonError.dragonIsMissing

You can throw anything that conforms to ErrorType protocol. For starters NSError conforms to this protocol but you probably would like to go with enum-based ErrorType which enables you to group multiple related errors, potentially with additional pieces of data, like this

enum DragonError: ErrorType {
    case dragonIsMissing
    case notEnoughMana(requiredMana: Int)
    ...
}


Main differences between new Swift 2 & 3 error mechanism and Java/C#/C++ style exceptions are follows:

  • Syntax is a bit different: do-catch + try + defer vs traditional try-catch-finally syntax.
  • Exception handling usually incurs much higher execution time in exception path than in success path. This is not the case with Swift 2.0 errors, where success path and error path cost roughly the same.
  • All error throwing code must be declared, while exceptions might have been thrown from anywhere. All errors are "checked exceptions" in Java nomenclature. However, in contrast to Java, you do not specify potentially thrown errors.
  • Swift exceptions are not compatible with ObjC exceptions. Your do-catch block will not catch any NSException, and vice versa, for that you must use ObjC.
  • Swift exceptions are compatible with Cocoa NSError method conventions of returning either false (for Bool returning functions) or nil (for AnyObject returning functions) and passing NSErrorPointer with error details.

As an extra syntatic-sugar to ease error handling, there are two more concepts

  • deferred actions (using defer keyword) which let you achieve the same effect as finally blocks in Java/C#/etc
  • guard statement (using guard keyword) which let you write little less if/else code than in normal error checking/signaling code.

Swift 1

Runtime errors:

As Leandros suggests for handling runtime errors (like network connectivity problems, parsing data, opening file, etc) you should use NSError like you did in ObjC, because the Foundation, AppKit, UIKit, etc report their errors in this way. So it's more framework thing than language thing.

Another frequent pattern that is being used are separator success/failure blocks like in AFNetworking:

var sessionManager = AFHTTPSessionManager(baseURL: NSURL(string: "yavin4.yavin.planets"))
sessionManager.HEAD("/api/destoryDeathStar", parameters: xwingSquad,
    success: { (NSURLSessionDataTask) -> Void in
        println("Success")
    },
    failure:{ (NSURLSessionDataTask, NSError) -> Void in
        println("Failure")
    })

Still the failure block frequently received NSError instance, describing the error.

Programmer errors:

For programmer errors (like out of bounds access of array element, invalid arguments passed to a function call, etc) you used exceptions in ObjC. Swift language does not seem to have any language support for exceptions (like throw, catch, etc keyword). However, as documentation suggests it is running on the same runtime as ObjC, and therefore you are still able to throw NSExceptions like this:

NSException(name: "SomeName", reason: "SomeReason", userInfo: nil).raise()

You just cannot catch them in pure Swift, although you may opt for catching exceptions in ObjC code.

The questions is whether you should throw exceptions for programmer errors, or rather use assertions as Apple suggests in the language guide.

这篇关于Swift语言中的错误处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆