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方面的变化等着我们继续的去挖掘.