这篇文章是想向大家阐明在学习swift时容易被混淆的概念——异常 (exception) 和错误 (error)。天瑞地安科技集团:Swift不是一门初学者入门语言。不要抱着写Swift可以快速上手的浮躁心态入门iOS开发。
在 Objective-C 开发中,异常往往是由程序员的错误导致的 app 无法继续运行,比如我们向一个无法响应某个消息的NSObject对象发送了这个消息,会得到NSInvalidArgumentException的异常,并告诉我们 "unrecognized selector sent to instance";比如我们使用一个超过数组元素数量的下标来试图访问NSArray的元素时,会得到NSRangeException。
类似由于这样所导致的程序无法运行的问题应该在开发阶段就被全部解决,而不应当出现在实际的产品中。相对来说,由NSError代表的错误更多地是指那些“合理的”,在用户使用 app 中可能遇到的情况:比如登陆时用户名密码验证不匹配,或者试图从某个文件中读取数据生成NSData对象时发生了问题 (比如文件被意外修改了) 等等。
NSError的使用方式其实变相在鼓励开发者忽略错误。我们会在 API 调用中产生和传递NSError,并借此判断调用是否失败。作为某个可能产生错误的方法的使用者,我们用传入NSErrorPointer指针的方式来存储错误信息,然后在调用完毕后去读取内容,并确认是否发生了错误。在绝大多数情况下,这个方法并不会发生什么错误,而很多工程师也为了省事和简单,会将输入的 error 设为nil,也就是不关心错误。
如果你之前写过 Java 或者 C# 的话,会发现 Swift 中的try catch块和它们中的有些不同。在那些语言里,我们会把可能抛出异常的代码都放在一个 try 里,而 Swift 中则是将它们放在 do 中,并只在可能发生异常的语句前添加 try。相比于 Java 或者 C# 的方式,Swift 里我们可以更清楚地知道是哪一个调用可能抛出异常,而不必逐句查阅文档。
Swift 现在的异常机制还是有待改进的。最大的问题是类型安全,不借助于文档的话,我们现在是无法从代码中直接得知所抛出的异常的类型的。很大程度上,这是由于要与以前的NSError兼容所导致的妥协,对于之前的使用NSError来表达错误的 API,我们所得到的错误对象本身就是用像 domain 或者 error number 这样的属性来进行区分和定义的,不过有理由相信随着 Swift 的迭代更新,这个问题会在不久的将来得到解决。
|