转眼间,Swift已经一岁多了。这种清新、时尚、类型安全、执行速度更快的语言逐渐深入开发者的心中。我也很喜欢这种新的编程语言。今年6月,一年一度的WWDC大会如期而至。在大会上,Apple发布了Swift2.0,它引入了许多新功能,以帮助开发人员更快、更轻松地构建应用程序。这里我也说说Swift2.0中值得大家关注的新特性。guard语句guard语句有点类似于if语句,它根据其关键字后面的表达式的布尔值来决定下一步执行什么。但是与if语句不同的是,guard语句只会有一个代码块,不像if语句可以ifelse多个代码块。那么guard语句到底有什么作用呢?顾名思义,就是守护。当guard语句判断后面表达式的布尔值为false时,就会执行下面代码块中的代码。如果为真,则将跳过整个guard语句。让我们来看看。我们以今年的高考为例。进入考场一般要检查身份证和准考证。我们写这样一个方法:funccheckup(person:[String:String!]){//检查身份证,如果没有带身份证,guardletid=person["id"]else{print("你不能不带身份证进考场!")return}//查看准考证,没有准考证不能进考场guardletexamNumber=person["examNumber"]else{print("没有准考证不能进考场!")return}//你的身份证和准考证齐全才能进考场print("你的身份证号是:\(id),你的考试准考证编号为:\(examNumber)。请进入考场!")}checkup(["id":"123456"])//没有准考证不能进入考场!checkup(["examNumber":"654321"])//没有准考证身份证,不能进考场!checkup(["id":"123456","examNumber":"654321"])//你的身份证号是:123456,准考证号是:654321请输入考场!上面代码中第一个guard语句用于检查身份证,如果没有检查到身份证,即表达式为false时,执行大括号中的代码并返回。第二个guard语句检查准考证,如果两张牌都完整,则执行最后一个print语句,上面两条guard语句的花括号内的代码不会执行,因为它们表达式的布尔值都是true.这里值得注意的是,id和examNumber可以用在guard语句之外,也就是说,在guard验证其表达式后,id和examNumber可以在整个方法的范围内使用并被解包。让我们用ifelse语句写一个类似的方法:funccheckupUseIf(person:[String:String!]){ifletid=person["id"],letexamNumber=person["examNumber"]{print("你的身份证号码是:\(id),考试准考证号为:\(examNumber)。请进入考场!")}else{print("证件不齐全,不能进入考场!")}print("你的身份证号是:\(id),准考证号是:\(examNumber)")//报异常}checkupUseIf(["id":"123456"])//证件不齐全,不能进入考场!checkupUseIf(["examNumber":"654321"])//证件不齐全checkupUseIf(["id":"123456","examNumber":"654321"])//你的身份证号是:123456,准考证号是:654321,请输入考场!我们可以看到用ifelse实现的方法明显不如guard并且id和examNumber的范围限制在if的第一个花括号内,如果超过这个范围,编译的时候会报错.从上面两个小例子不难看出,guard语句就像一个称职的守卫,层层把关,防止一切不被允许的事情发生,真是太棒了,并使代码更具可读性。异常处理在Swift1.0时代没有异常处理和抛出机制。如果要处理异常,必须使用ifelse语句或者switch语句进行判断处理,或者通过闭包形式的回调函数进行处理,或者通过NSError进行处理。以上这些方法都不能像Java中的trycatch异常控制语句那样从容从容地处理异常,而且还会降低代码的可读性。当Swift2.0到来时,一切都不同了。在Swift2.0中,Apple提供了由五个关键字组成的异常控制处理机制:throws、throw、try、do、catch。让我们举个例子看看如何使用它。我以手机扫朋友圈为例。首先,我们需要定义异常枚举。在Swift2.0中,Apple提供了ErrorType协议,需要我们自定义异常枚举来遵循:enumWechatError:ErrorType{caseNoBattery//手机没有电池caseNoNetwork//手机没有网络caseNoDataStream//手机没有流量}我们定义了导致无法刷微信的错误枚举'wechatError'。然后确定一个检查是否可以刷微信的方法checkIsWechatOk():funccheckIsWechatOk(isPhoneHasBattery:Bool,isPhoneHasNetwork:Bool,dataStream:Int)throwones{asBguardisPhone.NoBattery}guardisPhoneHasNetworkelse{throwWechatError.NoNetwork}guarddataStream>50else{throwWechatError.NoDataStream}}这里注意方法名后面有一个throws关键字,意思是将方法产生的异常向上层抛出。在方法体中使用guard语句判断各种状态,然后使用throw关键字抛出对应的异常。然后我们定义刷微信的方法:天都黑了!”)}catchWechatError.NoBattery{print("手机没电了,什么鬼!")}catchWechatError.NoNetwork{print("没有网络,我们洗单机玩吧!")}catchWechatError.NoDataStream{print("没有流量,上wifi!")}catch{print("该死!")}}playWechat(true,isPhoneHasNetwork:true,dataStream:60)//轻松刷卡,直到天黑!playWechat(true,isPhoneHasNetwork:false,dataStream:60)//没有网络,单机玩吧!playWechat(false,isPhoneHasNetwork:true,dataStream:60)//手机没电了,好鬼!playWechat(true,isPhoneHasNetwork:true,dataStream:30)//没有流量,上wifi!在上面的代码示例中,在方法前使用try关键字来检查是否可以扫描微信,表示允许该方法抛出异常,然后使用docatch控制语句捕获抛出的异常,然后进行相关的逻辑处理。这套异常处理机制让Swift更加全面和安全,提高了代码的可读性,很棒。协议扩展在Swift1.0时代,一个协议(Protocol)基本上类似于一个接口,定义了几个属性和方法供类、结构体和枚举类遵循和实现。在Swift2.0中,您可以扩展协议的属性或方法,类似于扩展类和结构。这将我们带到面向协议编程的章节。在Swift中,大部分基础对象都遵循CustomStringConvertible协议,比如Array和Dictionary(Swift1.0中的Printable协议),定义了description方法,通过print方法打印对象。现在我们向协议扩展一个方法来打印大写内容:self.description.uppercaseString)"}}print(arr.upperDescription)//"[HELLO,WORLD]"如果想在Swift1.0时代实现上面例子的效果,那么我们需要分别进行Array和Dictionary扩展,所以协议的扩展大大提高了我们的编程效率,也让代码更加简洁易读。打印语句的变化在Swift1中,有两种在控制台打印语句的方法,'println()'和'print()',前者换行打印,后者连续打印。在Swift2中,'println()'已成为过去,取而代之的是两者的组合。如果要打印换行,需要这样写:print("Iwanttonewline!",appendNewline:true)availablecheck作为iOS开发者,大家都希望使用最新版本的iOSAPI进行开发,省事和努力。但是往往事与愿违,因为我们经常需要适配旧版本的iOS,这就会面临一个问题。一些新特性或者一些类在老版本的iOS中不能使用,所以在编码过程中经常修改iOS版本。判断,像这样:ifNSClassFromString("NSURLQueryItem")!=nil{//iOS8orhigher}else{//iOS8之前的版本}以上只是一种方式,Swift2.0之前没有标准的模式或机制帮助开发者判断iOS版本,容易出现遗漏。在Swift2.0到来之后,我们有一个标准的方式来做这个:if#available(iOS8,*){//iOS8orlaterletqueryItem=NSURLQueryItem()}else{//beforeiOS8}这个特性让我们太高兴了.do-while语句改名经典的do-while语句改名改成了repeat-while:vari=0repeat{i++print(i)}whilei<10感觉更直观。defer关键字在某些语言(如Java)中有类似try/finally的控制语句。这条语句允许我们执行必须在finally代码块中执行的代码,而不管之前发生了什么。在Swift2.0中,Apple提供了defer关键字,可以让我们达到同样的效果。funccheckSomething(){print("CheckPoint1")doSomething()print("CheckPoint4")}funcdoSomething(){print("CheckPoint2")defer{print("Cleanuphere")}print("CheckPoint3")}checkSomething()//CheckPoint1,CheckPoint2,CheckPoint3,Cleanuphere,CheckPoint4在上面的例子中,我们可以看到在打印出“CheckPoint2”之后,并没有打印出“Cleanuphere”,而是“CheckPoint3”。这就是延迟的功能。print("Cleanuphere")被延迟。我们再看一个I/O的例子://伪代码funcwriteSomething(){letfile=OpenFile()letioStatus=fetchIOStatus()guardioStatus!="error"else{return}file.write()closeFile(file)}上面的例子它是I/O操作的伪代码。如果获取到的ioStatus是正常的,那么这个方法是没有问题的。如果获取到的ioStatus错误,会被guard语句捕获,执行返回操作。在这种情况下,closeFile(file)将永远存在。不会再执行了,刚刚就出现了严重的bug。让我们看看如何使用defer来解决这个问题://伪代码funcwriteSomething(){letfile=OpenFile()defer{closeFile(file)}letioStatus=fetchIOStatus()guardioStatus!="error"else{return}file.write()}我们把closeFile(file)放在defer代码块中,这样即使ioStatus出错,在执行return之前也会先执行defer中的代码,保证无论发生什么情况,file都会被最后关闭。defer是保证我们代码健壮性的另一个特性,我非常喜欢它。当然,Swift2.0的新特性不止于此,但你一眼就能看出来。Swift2.0力求将更快、更安全做到极致。这是开发商的福音。让我们一起享受这美妙的语言吧。
