Swift2.新特性

翻译自:原文地址

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上运行上述代码,你可以看到如下输出:

现在你可给扩展Awesome协议添加一个调用了awesomenessPercentage()方法结果的awesomenessIndex属性:

<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>

9.Print()完全取代Println()

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,265评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,078评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,852评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,408评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,445评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,772评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,921评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,688评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,130评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,467评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,617评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,276评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,882评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,740评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,967评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,315评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,486评论 2 348

推荐阅读更多精彩内容