在 Swift 中调用使用throws 声明的函数时,必须使用try 或try! 注释函数调用位置。例如,给定一个抛出函数:
func willOnlyThrowIfTrue(value: Bool) throws {
if value { throw someError }
}
这个函数可以这样调用:
func foo(value: Bool) throws {
try willOnlyThrowIfTrue(value)
}
这里我们用try对调用进行注解,告诉读者这个函数可能会抛出异常,后面的任何代码行都可能不会被执行。我们还必须用throws注释这个函数,因为这个函数可能会抛出异常(即当willOnlyThrowIfTrue()抛出时,foo会自动向上重新抛出异常。
如果你想调用一个声明为可能抛出的函数,但你知道它不会抛出,因为你给了它正确的输入,你可以使用try!。
func bar() {
try! willOnlyThrowIfTrue(false)
}
这样,当您保证代码不会抛出异常时,您不必添加额外的样板代码来禁用异常传播。
try! 在运行时强制执行:如果您使用try! 并且函数最终抛出,那么您的程序的执行将因运行时错误而终止。
大多数异常处理代码应如上所示:要么在异常发生时简单地向上传播异常,要么设置条件以排除其他可能的异常。代码中其他资源的任何清理都应通过对象销毁(即deinit())或有时通过defered 代码进行。
func baz(value: Bool) throws {
var filePath = NSBundle.mainBundle().pathForResource("theFile", ofType:"txt")
var data = NSData(contentsOfFile:filePath)
try willOnlyThrowIfTrue(value)
// data and filePath automatically cleaned up, even when an exception occurs.
}
如果您出于某种原因清理了需要运行但不在deinit() 函数中的代码,则可以使用defer。
func qux(value: Bool) throws {
defer {
print("this code runs when the function exits, even when it exits by an exception")
}
try willOnlyThrowIfTrue(value)
}
大多数处理异常的代码只是让它们向上传播给调用者,通过deinit() 或defer 进行清理。这是因为大多数代码不知道如何处理错误;它知道出了什么问题,但它没有足够的信息来说明一些更高级别的代码正在尝试做什么,以便知道如何处理错误。它不知道向用户显示对话框是否合适,或者是否应该重试,或者是否合适。
但是,更高级别的代码应该确切地知道在发生任何错误时该怎么做。因此,异常允许特定错误从最初发生的地方冒泡到可以处理的地方。
通过catch 语句处理异常。
func quux(value: Bool) {
do {
try willOnlyThrowIfTrue(value)
} catch {
// handle error
}
}
您可以有多个 catch 语句,每个语句捕获不同类型的异常。
do {
try someFunctionThatThowsDifferentExceptions()
} catch MyErrorType.errorA {
// handle errorA
} catch MyErrorType.errorB {
// handle errorB
} catch {
// handle other errors
}
有关例外情况的最佳做法的更多详细信息,请参阅http://exceptionsafecode.com/。它专门针对 C++,但在研究了 Swift 异常模型之后,我相信基础知识也适用于 Swift。
有关 Swift 语法和错误处理模型的详细信息,请参阅书籍The Swift Programming Language (Swift 2 Prerelease)。