转眼间,Swift已经一岁多了,这门新鲜、语法时尚、类型安全、执行速度更快的语言已经渐渐的深入广大开发者的心。
今年6月,一年一度的WWDC大会如期而至,在大会上Apple发布了Swift 2.0,引入了很多新的特性,以帮助开发者能更快,更简单的构建应用。我在这里也说道说道Swift 2.0中值得大家注意的新特性。
guard语句
guard语句和if语句有点类似,都是根据其关键字之后的表达式的布尔值决定下一步执行什么。但与if语句不同的是,guard语句只会有一个代码块,不像if语句可以if else多个代码块。
那么guard语句的作用到底是什么呢?顾名思义,就是守护。guard语句判断其后的表达式布尔值为false时,才会执行之后代码块里的代码,如果为true,则跳过整个guard语句,我们举例来看看。
我们以今年高考为例,在进入考场时一般都会检查身份证和准考证,我们写这样一个方法:
func checkup(person: [String: String!]) { // 检查身份证,如果身份证没带,则不能进入考场 guard let id = person["id"] else { print("没有身份证,不能进入考场!") return } // 检查准考证,如果准考证没带,则不能进入考场 guard let examNumber = person["examNumber"] else { print("没有准考证,不能进入考场!") return } // 身份证和准考证齐全,方可进入考场 print("您的身份证号为:\(id),准考证号为:\(examNumber)。请进入考场!") } checkup(["id": "123456"]) // 没有准考证,不能进入考场! checkup(["examNumber": "654321"]) // 没有身份证,不能进入考场! checkup(["id": "123456", "examNumber": "654321"]) // 您的身份证号为:123456,准考证号为:654321。请进入考场!
上述代码中的第一个guard语句用于检查身份证,如果检查到身份证没带,也就是表达式为false时,执行大括号里的代码,并返回。第二个guard语句则检查准考证。
如果两证齐全,则执行最后一个打印语句,上面的两个guard语句大括号内的代码都不会执行,因为他们表达式的布尔值都是true。
这里值得注意的是,id和examNumber可以在guard语句之外使用,也就是说当guard对其表达式进行验证后,id和examNumber可在整个方法的作用域中使用,并且是解包后的。
我们再用if else语句写一个类似的方法:
func checkupUseIf(person: [String: String!]) { if let id = person["id"], let examNumber = person["examNumber"] { print("您的身份证号为:\(id),准考证号为:\(examNumber)。请进入考场!") } else { print("证件不齐全,不能进入考场!") } print("您的身份证号为:\(id),准考证号为:\(examNumber)") // 报异常 } checkupUseIf(["id": "123456"]) // 证件不齐全,不能进入考场! checkupUseIf(["examNumber": "654321"]) // 证件不齐全,不能进入考场! checkupUseIf(["id": "123456", "examNumber": "654321"]) // 您的身份证号为:123456,准考证号为:654321。请进入考场!
我们可以看到用if else实现的方法显然不如guard实现的那么精准。而且id和examNumber的作用域只限在if的第一个大括号内,超出这个作用域编译就会报错。
通过上述两个小例子不难看出,guard语句正如一个称职的守卫,层层把关,严防一切不允许发生的事,并且让代码具有更高的可读性,非常棒。
异常处理
在Swift 1.0时代是没有异常处理和抛出机制的,如果要处理异常,要么使用if else语句或switch语句判断处理,要么使用闭包形式的回调函数处理,再要么就使用NSError处理。以上这些方法都不能像Java中的try catch异常控制语句那样行如流水、从容不迫的处理异常,而且也会降低代码的可读性。当Swift 2.0到来后,一切都不一样了。
在Swift 2.0中Apple提供了使用throws、throw、try、do、catch这五个关键字组成的异常控制处理机制。下面我们来举例看看如何使用,我用使用手机刷朋友圈为例。
首先我们需要定义异常枚举,在Swift 2.0中Apple提供了ErrorType协议需要我们自定义的异常枚举遵循:
enum WechatError: ErrorType { case NoBattery // 手机没电 case NoNetwork // 手机没网 case NoDataStream // 手机没有流量 }
我们定义了导致不能刷微信的错误枚举’wechatError。然后定义一个检查是否可以刷微信的方法checkIsWechatOk():
func checkIsWechatOk(isPhoneHasBattery: Bool, isPhoneHasNetwork: Bool, dataStream: Int) throws { guard isPhoneHasBattery else { throw WechatError.NoBattery } guard isPhoneHasNetwork else { throw WechatError.NoNetwork } guard dataStream > 50 else { throw WechatError.NoDataStream } }
这里注意,在方法名后有throws关键字,意思为该方法产生的异常向上层抛出。在方法体内使用guard语句对各种状态进行判断,然后使用throw关键字抛出对应的异常。然后我们定义刷微信的方法:
func playWechat(isPhoneHasBattery: Bool, isPhoneHasNetwork: Bool, dataStream: Int) { do { try checkIsWechatOk(isPhoneHasBattery, isPhoneHasNetwork: isPhoneHasNetwork, dataStream: dataStream) print("放心刷,刷到天昏地暗!") } catch WechatError.NoBattery { print("手机都没电,刷个鬼啊!") } catch WechatError.NoNetwork { print("没有网络哎,洗洗玩单机吧!") } catch WechatError.NoDataStream { print("没有流量了,去蹭Wifi吧!") } catch { print("见鬼了!") } } playWechat(true, isPhoneHasNetwork: true, dataStream: 60) // 放心刷,刷到天昏地暗! playWechat(true, isPhoneHasNetwork: false, dataStream: