调用throws
在Swift中声明的函数时,必须使用try
或注释函数调用站点try!
。例如,给定一个throwing函数:
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()
)或有时通过defer
ed代码来进行。
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语法和错误处理模型的详细信息,请参见《 Swift编程语言(Swift 2预发行版)》。