本篇分两部分:
1、错误和异常处理
2、Swift 中的断言
1、错误和异常处理
在 OC 开发中,我们通常会将 error 置为 nil
NSError *error; BOOL success = [data writeToFile: path options: options error: &error]; if(error) { // 错误信息 }
在绝大多数情况下,这个方法并不会发生什么错误,所以我们将 error 直接设置为 nil。但是出错的时候可能就会无从下手进行调试。在 Swift 中引入了异常机制,这让我们老牌程序员感到异常亲切,因为在 java 或 C# 中我们会经常使用。但是与 java 不同的是,Swift 中用的是 do...catch 语法,然后在可能跑出异常的地方来用 try 进行修饰,而 java 中直接将可能抛出异常的代码块放到 try...catch 中。swift 相较 java 会更快速的锁定异常代码的行数,而 java 可能需要一步步调试才能发现 try...catch 中那句发生了错误,但我并不认为这是个优点,如果 Swift 中多处都会抛出同样的异常,每句都去修饰的话会导致代码异常臃肿。
enum LoginError: ErrorType { case UserNotFound, UserPasswordNotMatch } func login(user: String, password: String) throws { if 1 < 2 { throw LoginError.UserNotFound } if 2 > 1 { throw LoginError.UserPasswordNotMatch } print("Login successfully.") } do { try login("onevcat", password: "123") } catch LoginError.UserNotFound { print("UserNotFound") } catch LoginError.UserPasswordNotMatch { print("UserPasswordNotMatch") }
2、Swift 中的断言
断言(assertion)在 Cocoa 开发里一般用来在检查输入参数是否满足一定条件,并对其进行“论断”,用于提高开发人员之间的沟通效率。
在判断某些输入参数是否满足条件时,我们程序员通常用 if 这样的条件控制来检测,如果遇到无法继续的情况就提前返回或跑出错误。但是这样导致了运行时的额外开销,对于像判断输入参数是否满足条件这样的情景,我们用断言处理将会更好。
swift 中为我们提供的断言方法:
func assert(@autoclosure condition: () -> Bool, @autoclosure _ message: () -> String = default, file:StaticString = default, line: UInt = default)
举一个简单的例子,比如我们的年龄不能小于0岁:
func convertAge(age: Int) -> Int { assert(age < 0, "输入的年龄不能小于0岁") return 0 } let xiaoMingAge = convertAge(-10) // 运行时错误: // assertion failed: // 输入的年龄不能小于0岁
断言最最基本的作用:
在遇到无法处理的输入时,运行会产生错误并抛出我们预设的信息来提醒调用这段代码的工程师。
断言的特点:
与我们自定义的 NSLog 类似,它是一个开发时的特性,只有在 Debug 编译的时候有效,而在运行时是不被编译执行的,因此并不会消耗运行时的性能。这些特点使得断言称为面向程序员在调试开发阶段非常适合的调试判断,而在代码发布时,我们也不需要刻意去把这些断言手动清除。
如果我们想要在 Debug 模式下强制禁用断言,在对应的 target 的 Build Setting 中,我们在 Swift Compiler - Custom Flags 中的 Other Swift Flags 中添加 -assert-config Release 来强制禁用断言,或者 -assert-config Debug 来强制启用断言。(不建议这么做)
注:OC 中的断言函数 NSAssert 在 Swift 中已被移除。