翻译自:原文地址
1.repeat-while替换了do-while
在Swift2中,使用循环时,repeat替换了do
在后面的章节,do关键字被用于其他语法特征
2.for-in语句中使用where
举例:当你循环遍历一个数组时,只有那些符合条件的元素可以被遍历<pre><code>let numbers = [20, 18, 39, 49, 68, 230, 499, 238, 239, 723, 332]
for number in numbers where number > 100{
print(number)
}
</pre></code>在上面的例子中近会输出大于100的数字。
3.if-case匹配
当swift刚刚发布时,switch语句有了很大改进,switch不仅可以匹配数值类型,并且可以匹配范围,下面给出一个范围匹配的例子:
<pre><code>let examResult=49
switch examResult{
case 0...49: print("Fail!")
case 50...100: print("Pass!")
default: break
}
</pre></code>在swift2中,也可以使用if-case进行范围匹配:
<pre><code>if case 0...49 = examResult{
print("Fail!")
}else if case 50...100 = examResult{
print("Pass!")
}</pre></code>if-case也可以进行模式匹配,下面是一个采用元组的例子:
<pre><code>let userInfo = (id: "petersmith", name: "Peter Smith", age: 18, email: "simon")
if case(,,0..<18,_){
print("You're not allowed to register an account because you're below 18.")
}else if case (_, _, _, let email) = userInfo where email == "" {
print("Your email is blank. Please fill in your email address.")
} else {
print("You are good to go!")
}
</pre></code>第一个if-case分支来判断用户的年龄是不是在18岁以上,“_”字符意味着“忽略的值”,这里仅仅关注的是用户的年龄。else if case用来判断email是否为空。在你使用if-case时,你可以产生一个临时绑定,这里在where语句里面用了一个临时绑定的email常量。
4.Guard语句
Swift2介绍了guard关键字,苹果的官方描述是这样说的:
A guard statement, like an if statement, executes statements depending on the Boolean value of an expression. You use a guard statement to require that a condition must be true in order for the code after the guard statement to be executed.
在介绍guard之前,先来看下面这个例子:
<pre><code>struct Article {
var title:String?
var description:String?
var author:String?
var totalWords:Int?
}
func printInfo(article: Article) {
if let totalWords = article.totalWords where totalWords > 1000 {
if let title = article.title{
print("Title: (title)")
}else{
print("Error: Couldn't print the title of the article!")
}
}else{
print("Error: Couldn't print the total word count!")
}
}
let sampleArticle = Article(title: "Swift Guide", description: "A beginner's
guide to Swift 2", author: "Simon Ng", totalWords: 1500)
printlnfo(sampleArticle)
</pre></code>在上面的代码中,用printInfo方法来打印文章的标题,并且仅打印超过1000个单词的文章信息,由于变量时可选类型(optionals),所以用if来判断可选值是不是nil,如果为nil,打印错误信息,如果在Playgrounds运行上述代码,那么就会打印文章的标题。
通常情况下,if-else语句形式如下:
<pre><code>if some coditions are met{
// something
if some conditons are met{
// something
}else{
// show errors or performs other operations
}
}else{
// show errors or performs other operations
}
</pre></code>如果有很多情况的需要判断,if-else语句就会多重嵌套,在编程上没有任何错误,但是减弱了代码的可读性。
guard语句就可解决这个问题,其语法如下:
<pre><code>guard conditons else{
// what to do if the condition is not met
}
// continue to perform normal actions
</pre></code>如果guard语句中的条件不满足,那么执行else分支,如果条件满足,那么跳过else分支,继续执行代码。
用guard重写上面的代码,就会变得更加清晰:
<pre><code>func printInfo(article: Article) {
guard let totalWords = article.totalWords where totalWords>1000 else{
print("Error: Couldn't print the total word count!")
return
}
guard let title = =article.title else{
print("Error: Couldn't print the title of the article!")
return
}
print("Title:(title)")
}
</pre></code>guard关注的是不满足的条件,跟他确切的说,每次只处理一个条件,避免了嵌套,因此,增强代码的阅读性。
5.异常处理
在开发APP或者其他程序的时候,需要处理出现的异常。例如,正在开发一个可以和云端连接的APP,那么就需要处理网络无法连接、云服务器无法连接等问题。
在之前的Swift版本中,并没有异常处理的机制。下面代码说明了之前的异常处理方式:
<pre><code>let request = NSURLRequest(URL: NSURL(string: "http://www.apple.com")!)
var response:NSURLResponse?
var error:NSError?
let data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: &error)
if error == nil {
print(response)
// Parse the data
} else {
// Handle error
}
</pre></code>当调用一个可能失败的方法时,可以传给它一个NSError对象,如果出现异常,这个对象会被赋予相应的错误值,通过判断它是否为nil就可以进行相应的处理。
注意:NSURLConnection.sendSynchronousRequest() 已经在IOS9中被弃用,由于大多数读者更加熟悉这个用法,在此仅进行举例。
try / throw / catch
在Swift2中,采用以try-catch-throw为关键字的异常处理模型,上面的代码就会变成这样:
<pre><code>let request = NSURLRequest(URL: NSURL(string: "http://www.apple.com")!)
var response:NSURLResponse?
do{
let data = try NSURLConnection.sendSynchronousRequest(request, returningResponse: &response)
print(response)
}catch {
print(error)
}
</pre></code>
现在你可以使用do-catch语句来捕获异常并且进行相应的处理。在调用的方法前采用try关键字。在Swift2中,在我们调用一个抛出异常的方法时,我们需要使用try关键字。那如何判断一个方法抛出了异常呢?当你在编辑器中输入方法时,抛出异常的方法会用throws关键字标识。
假设现在有一个汽车发动机模型,在下面条件下,发动机启动失败:
- No fuel
- Oil leakage
- Low battery
在Swift中,异常类型需要实现ErrorType协议,在这个例子中,你可以定义一个实现ErrorType的枚举类型:
<pre><code>enum CarEngineErrors: ErrorType {
case NoFuel
case OilLeak
case LowBattery
}
</pre></code>接着,生成一个可以抛出异常的方法,在声明中用throws关键字:
<pre><code>let fuelReserve = 20.0
let oilOK = true
let batteryReserve = 0.0
func checkEngine() throws{
guard fuelReserve > 0.0 else{
throw CarEngineErrors.NoFuel
}
guard oilOK else{
throw CarEngineErrors.OilLeak
}
guard batteryReserve > 0.0 else{
throw CarEngineErrors.LowBattery
}
}</pre></code>调用checkEngine方法时,需要在前面加上try关键字:
<pre><code>func startEngine(){
try checkEngine()
}</pre></code>如果你将上述代码在Playgrounds运行时,会报错,原因是没有进行异常处理,Swift里的异常处理机制要求需要用do-catch语句捕获所有的异常并进行处理。
<pre><code>func startEngine(){
do{
try checkEngine()
print("Engine started", appendNewline: true)
} catch CarEngineErrors.NoFuel {
print("No Fuel!")
} catch CarEngineErrorss.OilLeak {
print("Oil Leak!")
} catch CarEngineErrors.LowBattery {
print("Low Battery!")
} catch {
print("Unknown reason!")
}
</pre></code>类似于switch语句,在Swift2中你需要处理每种可能出现的异常。
6.defer
在Java中,有一个类似的异常处理机制try-catch-finally无论是否存在异常finally中的语句都会执行。
Swift2通过defer关键字提供了相似的语句,无论是否存在异常,defer中的语句在当前范围运行结束时都会得到执行,继续用上面的例子,将checkEngine()作如下修改:
<pre><code>let fuelReserve = 20.0
let oilOK = true
let batteryReserve = 0.0
func checkEngine() throws{
defer{
print("this is the defer statement")
}
guard fuelReserve > 0.0 else{
throw CarEngineErrors.NoFuel
}
guard oilOK else{
throw CarEngineErrors.OilLeak
}
guard batteryReserve > 0.0 else{
throw CarEngineErrors.LowBattery
}
}</pre></code>然后运行startEngine()方法,此时在playgrounds得到的结果:
Low Battery!
this is the defer statement
defer语句尤其可以应用于清空操作:
<pre><code>func aMethod() throws {
// Open some resources such as opening a file
defer {
// Release the resources and perform cleanup operations (e.g. close a file descriptor)
}
// Error handling (e.g. fails to load the file)
// Do something with the resources
}
</pre></code>
7.协议扩展
在Swift1.2中,你可以使用扩展现有的类、结构体或者枚举,Swift2还允许扩展协议类型。通过协议扩展,你可以给协议添加方法和属性。下面是协议扩展的一个例子。
定义一个Awesome的协议:
<pre><code>protocol Awesome {
func awesomenessPercentage() -> Float
}
</pre></code>定义两个实现Awesome协议的类:
<pre><code>class Dog: Awesome {
var age: Int!
func awesomenessPercentage() -> Float {
return 0.85
}
class Dog: Awesome {
var age: Int!
func awesomenessPercentage() -> Float {
return 0.45
}
let dog = Dog()
dog.awesomenessPercentage()
let cat = Cat()
cat.awesomenessPercentage()
}
</pre></code>在Playgrounds上运行上述代码,你可以看到如下输出:
<pre><code>extension Awesome {
var awesomenessIndex: Int {
get{
return Int(awesomenessPercentage() * 100)
}
}
}
</pre></code>通过扩展协议,所以实现协议的类就可以使用协议的awesomenessIndex属性。
8.Availability 检查
当在多个IOS版本下开发开发APP时,会使用最新版本的API接口,这使得在老的版本下运行时会出现异常。在Swift2之前,并没有相应的检查。NSURLQueryItem类仅能在不低于IOS8的版本下使用,如果在之前的版本使用就会倒是异常或程序崩溃,为了避免异常你可能会这样进行检查:
<pre><code>if NSClassFromString("NSURLQueryItem") != nil {
// iOS 8 or up
} else{
// Earlier iOS versions
}
</pre></code>但是从Swift2之后,有了相应的API的可用性检查,如下所示:
<pre><code>@available(iOS 9, *)
class SuperFancy {
// implementation
}</pre></code>可以在if语句中使用#avaliable关键字,“”表示能够支持的最低版本,当然也可以使用guard代替if*:
<pre><code>guard #available(iOS 8.4, OS X 10.10, *) else {
// what to do if it doesn't meet the minimum OS requirement
return
}</pre></code>