Swift 2.0 新特性
Swift2.0 算是一个大得版本更新.新增或修改了很多的特性.出来这么久了,我也把我练手写的知乎日报全部转换成了Swfit2.0.其中还是遇到了一些问题.因此,趁有空,就尝试总结一下Swift2.0的一些新特性或新的变化.
PS:本文写的时候采用的是 Swift2.0+Xcode7 beta4 的环境.
1.guard语句
Swift2.0中新引入了一个关键字guard用于条件的判断处理.它和if语句比较类似,都是通过一个boolean值来决定流程的走向.但是与if语句不同的是.guard语句只会有一个代码块.没有像if else那样有多个guard else.
那么guard到底有何作用呢?guard允许在一个代码周期中提前退出.也就是说,在guard关键字后接一个布尔表达式,只有当值为false的时候,才会执行else后的内容.如果值为true,那么就跳过这个guard代码块.
guard语句最常见的用法就是替代if做参数的合法性校验.
比如在以前:
|
|
向上面的例子那样,如果每一个参数都使用if语句来判断,那么这样的代码写起来非常的繁琐.读起来也不是很清晰.基于这种的情况,Swift2.0增加了guard关键字.把上面的代码改成使用guard的写法就会成这样:
|
|
这样写比起以前使用if来做判断,代码的可读性更强了.并且Optaion类型的变量的解包可以在全局可见了.这在网络编程中解析JSON等是非常有用的.
guard除了用于入参的校验和可选类型的解包外.还可以用于抛出异常以及结合available做函数的检查:
|
|
2.协议扩展
在之前的Swift中,协议(Protocol)其实相当于JAVA中的接口,可以定义若干的方法以及属性.然后其他的类、结构体、枚举等都继承这个协议.然后有各自的实现.而现在,在Swift2.0中,可以对协议进行扩展(extension),就和给一般的Class进行扩展一样.并且,同JDK1.8一样,现在协议允许拥有默认的方法实现了.这样就大大的增加了编程的灵活度.避免了当需要修改协议时候,需要修改全部实现该协议的类.
举一个例子:
|
|
在swift2.0中很多的协议都被苹果公司增加了扩展. 比如CollectionType这个协议.所有的集合类型都遵循了这个协议,然后在swift2.0中增加了若干的扩展:
|
|
等等.
这样就可以在不改变原有协议的基础上给协议增加了若干的方法:
|
|
3.Available检查
由于在苹果的生态环境中,基本上每一年都会推出新的OS,每年在发布会上都会说新的操作系统又新增了好多好多的API.好处当然是增加了很多功能,坏处也是显而易见的—-不同版本间的API存在兼容的问题.比如我们调用了一个IOS9中新增的方法,那么这个应用程序运行在了IOS8上,这个时候如果我们不进行系统的版本测试的话,那么我们的应用就会直接的崩溃掉,这显然不是我们所期望的.
为了解决这个问题,在Swift2.0中新引入了#available.配合Available检查,新的Swift编译器,也会在编译的时候就进行检测,当我们在低版本的OS中使用高版本的API的时候,编译器会直接的报错.而当编译器帮我们检测到API版本问题后,接下来就需要我们使用#available语法进行处理了.
#available的使用语法是:
|
|
前面的platform name version表示的是在平台的版本,允许有多个.
后面的* 表示的是其他平台,例如Watch OS
|
|
这样就可以使用一套代码来完成不同平台的正确编译与运行了.这对我们现在的开发有了很大的便利.
4.defer关键字
由于我是学JAVA的,所以当学习Swift的时候就思考过一个问题:在Swift中有没有类似于JAVA中try/finally的语法.也就是说无论前面的代码如何执行,在离开这个代码块之前,一定要执行一段逻辑.很遗憾的是我在swift1中没有发现类似的语法.而在Swift2.0中,Apple提供了这个功能,也就是新引入的defer关键字.
defer关键字允许包括一个代码块.然后让这段代码块延迟到defer所在域的最后执行.这样说起来有第一点抽象,看一个例子就明白了.
|
|
上面的代码有一个问题,那就是如果file.readline方法抛出异常的时候,那么 这段代码最后的close(file)方法可能就不会执行了,这就造成了资源的未关闭问题.
那么如果我们使用defer来修正这个问题,就会这样:
|
|
在上面的代码中,有一个defer代码块.其中编写了文件关闭的逻辑. 而这段逻辑就会在整个if作用域的最后执行,无论是程序是正常的走出if,还是由于异常而跳出if.这样就保证了无论如何程序都会关闭文件.
这里有一个地方需要注意的是多个defer的调用顺序,如果是在不同的作用域中,那么defer的执行顺序是从里到外的.而如果是在同一个作用域中,defer的执行顺序是自下而上的.这和平时的代码调用顺序是相反的.
|
|
上面这段代码最后打印出来的信息是:
1-1
1-2
2-1
2-3
2-4
2-2
1-3
大家注意一下这个的打印顺序,体会一下就明白了.
5.异常处理
上面说完了类似于JAVA中的try-finally,下面就来说说try-catch.
在Swift1中是没有异常处理以及抛出异常的,如果要处理异常.大多数情况下都是使用NSError或者闭包回调的方式来处理的.这些方法都没法像JAVA中的try-catch一样方便简洁的处理异常.虽然现在在JAVA界中现在有人觉得随意的抛出异常是一种不负责任的做法,会导致程序的可读性降低,并且开始反思有没有一种更好的方式来处理异常,但就目前来说,无疑是最好的方式.
在Swift2.0中,苹果提供了throws throw do catch try 这几个关键字来处理异常.
throws关键字写在一个方法签名的后面,返回值前,用于标识这个方法是会抛出异常的.throw关键字用于在代码块中抛出一个异常do关键字用于包裹一个代码块,形成一个do-catch作用域,来捕获异常catch关键字用于捕获某种异常,并且申明异常的处理逻辑try关键字用于调用某个会抛出异常的方法前,用于标识会尝试调用这个方法
例如:
|
|
- 首先,需要定义一个异常,和
JAVA中所有的异常都需要实现Throwable接口一样,在Swift2中异常是需要遵循ErrorType协议. 这里只是定义了一个异常的枚举. - 然后定义一个方法,并用
throws关键字来标志这个函数会抛出异常.但是这个关键字后面不需要申明到底抛出什么异常 - 接着在方法中使用
throw抛出一个异常.这个和JAVA类似. - 在调用
doSomeThing方法的地方使用do-catch来捕获异常.注意的是,这个地方apple又任性了一把,没有使用其他语言中通常使用的try-catch. - 在具体调用会抛出异常的方法时,使用
try关键字来标识.这样做有一个好处,就是可以一眼就看出在一个代码域中到底是哪可能会抛出异常.而不是将所有的代码都混在try-catch作用域中. 在
do-catch语法中,同try-catch一样,也是允许有多个catch代码块的.比如:1234567do{try doSomeThing(-1)}catch AppException.IllegalArgumentException{print("xxx")}catch AppException.IllegalFormatException{print("aaaa")}同可选类型的解包一样.
try也支持try!的写法.用于表示在明确的知道某一个throwing的方法不会抛出异常的情况下,使用try!就可以不用捕捉异常了.比如:1try! doSomeThing(10)
当然,现在Swift2.0中的异常捕获还有完善的地方,比如还没有区分运行时异常,非运行时异常,错误等等.但这已经是一个好的开始,期望在以后的版本中继续完善.
6.print改变
Apple已经把它的简洁的基因发挥到了极致了.居然想到了把从C语言就开始的println与print函数统一成了一个func print<T>(value: T, appendNewline: Bool)函数.第二个参数就是用于表示是否起新的一行. 默认是true.
以后学编程的第一个例子再也不是
|
|
7.do-while语句重命名
由于do关键字已经被用于了异常的捕获了.如果这个地方再使用do-while就有可能产生歧义.因此,apple也把这个从C语言开始就有的语法给改了名字:repeat-while.幸好,只是改了一个名字,还是同样的配方,还是同样的味道 ^.^
8.重新可以使用performSelector
performSelector方法在Swift1中被Apple认为有安全的问题而去掉了.然后,为了实现相同的功能,广大码农想了千奇百怪的办法.比如使用NSThread.detachNewThreadSelector:,比如NSTimer.scheduledTimerWithTimeInterval:,又比如sendAction:.
不过在Swift2.0中,Apple又在NSObjectProtocol协议中恢复了这个方法的调用.
现在可以方便的使用了
|
|
比如:
|
|
注意,这个方法在Playground中还是不能使用哈.
9.更强的语言结构性
由于扩展协议功能的出现,Apple把大量原来非面向对象的全局函数都封装到了各个协议中.让整个Swift2的语言结构性更强了.比如:
|
|
10.枚举的递归
在Swift中枚举类型是非常的强大的.它不仅可以拥有自己的属性,自己的方法.还可以遵循协议.极端点来说上来说,光使用枚举和结构体,就能把一个程序写完.
在Swift2.0中枚举又得到了增强,现在可以递归的定义枚举类型了.
什么叫递归的枚举喃?就是在枚举定义中引用自己,看一个例子就明白了:
|
|
看到了没,在定义Tree.Branch枚举的时候允许传入两个参数,并且这两个参数又是Tree枚举的.这就形成了枚举的递归.这样做有什么用呢?它其实扩大了枚举的使用场景.通过枚举就可以构建很复杂的数据结构和业务逻辑了.
比如:
|
|
11.增强化的模式匹配
在Swift2.0中强化了模式匹配,现在对于控制流增加了很多种组合.比如:if/case while/case guard/case for-in/case等等,并且上述的语法都允许像switch/case那样后面接上where做判断.
比如:
|
|
上面例子说明,if/case的用法,它和switch中的case其实是一样的.如果满足case后的条件,那么就执行if中的操作.这样像上例那样只有一个分支的枚举选择,就不需要使用switch语句了.
增强的模式匹配不光是可以用在枚举类型上.对于可选类型的解包操作同样的奏效.比如:
|
|
直接一步就搞定了,比以前方便了.
结束语
Swift2.0是一个大版本,有着许多优化与改动.经过这一次的改变,Swift2.0变得更加的友好、方便、安全,大大的增加了我们的开发体验.这里只介绍了其中的一些大点的改动,更多的API方面的变化等着我们继续的去挖掘.