我在swift中遇到了这种愚蠢的行为,其中强制解包一个可选项不会传播.
从文档:
试着用!访问不存在的可选值会触发运行时错误.在使用之前,请务必确保可选项包含非零值!强行解开它的价值.
重现:
func foo(bar:String?) throws{ print(bar!); }
和
try foo(nil);
这对我来说似乎不合逻辑或一致,我找不到有关此主题的任何文档.
这是设计的吗?
从文档:
错误处理
错误处理是响应程序中的错误条件并从中恢复的过程.Swift为在运行时抛出,捕获,传播和操纵可恢复的错误提供了一流的支持.
...
代表和抛出错误
在Swift中,错误由符合
ErrorType
协议的类型的值表示.此空协议表示类型可用于错误处理.
(注意:ErrorType
已Error
在Swift 3中重命名)
因此,try/catch
您处理Swift错误(符合ErrorType
协议的类型的值)是throw
n.这与运行时错误和运行时异常完全无关(并且与NSException
Foundation库无关).
请注意,有关错误处理的Swift文档甚至不使用"exception"一词,唯一的例外(!)在(强调我的)中:
注意
Swift中的错误处理类似于其他语言中的异常处理,使用了try,catch和throw关键字.与许多语言中的异常处理不同 - 包括Swift中的Objective-C-error处理不涉及展开调用堆栈,这可能是计算上昂贵的过程.因此,throw语句的性能特征与return语句的性能特征相当.
解包nil
不是throw
Swift错误(可以传播)并且无法处理的选项
try
.
您必须使用众所周知的技术,如可选绑定,可选链接,检查nil
等.
这个"自解释"示例可以帮助您查看引发运行时异常和抛出符合ErrorType协议的错误E之间的区别.
struct E: ErrorType{} func foo(bar:String?) throws { if let error = bar where error == "error" { throw E() } print(bar, "is valid parameter, but don't try to access bar.characters, it crash your code! (if bar == nil)") // here is everything OK let bar = bar! // but here it crash!! _ = bar.characters } do { try foo("error") // next line is not accessible here ... try foo(nil) } catch { print("\"error\" as parameter of foo() throws an ERROR!") } do { try foo(nil) // fatal error: unexpectedly found nil while unwrapping an Optional value } catch { }
它打印
"error" as parameter of foo() throws an ERROR! nil is valid parameter, but don't try to access bar.characters, it crash your code! (if bar == nil) fatal error: unexpectedly found nil while unwrapping an Optional value
引发运行时异常是代码中的致命错误.