Swift2.新特性

翻译自:原文地址

1.repeat-while替换了do-while

在Swift2中,使用循环时,repeat替换了do
在后面的章节,do关键字被用于其他语法特征

2.for-in语句中使用where

举例:当你循环遍历一个数组时,只有那些符合条件的元素可以被遍历

let numbers = [20, 18, 39, 49, 68, 230, 499, 238, 239, 723, 332]

for number in numbers where number > 100{

print(number)

}

在上面的例子中近会输出大于100的数字。

3.if-case匹配

当swift刚刚发布时,switch语句有了很大改进,switch不仅可以匹配数值类型,并且可以匹配范围,下面给出一个范围匹配的例子:

let examResult=49

switch examResult{

case 0...49: print("Fail!")

case 50...100: print("Pass!")

default: break

}

在swift2中,也可以使用if-case进行范围匹配:
if case 0...49 = examResult{

print("Fail!")

}else if case 50...100 = examResult{

print("Pass!")

}

if-case也可以进行模式匹配,下面是一个采用元组的例子:
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!")

}

第一个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之前,先来看下面这个例子:

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)

在上面的代码中,用printInfo方法来打印文章的标题,并且仅打印超过1000个单词的文章信息,由于变量时可选类型(optionals),所以用if来判断可选值是不是nil,如果为nil,打印错误信息,如果在Playgrounds运行上述代码,那么就会打印文章的标题。
通常情况下,if-else语句形式如下:
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

}

如果有很多情况的需要判断,if-else语句就会多重嵌套,在编程上没有任何错误,但是减弱了代码的可读性。

guard语句就可解决这个问题,其语法如下:

guard conditons else{

// what to do if the condition is not met

}

// continue to perform normal actions

如果guard语句中的条件不满足,那么执行else分支,如果条件满足,那么跳过else分支,继续执行代码。

用guard重写上面的代码,就会变得更加清晰:

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

}

guard关注的是不满足的条件,跟他确切的说,每次只处理一个条件,避免了嵌套,因此,增强代码的阅读性。

5.异常处理

在开发APP或者其他程序的时候,需要处理出现的异常。例如,正在开发一个可以和云端连接的APP,那么就需要处理网络无法连接、云服务器无法连接等问题。

在之前的Swift版本中,并没有异常处理的机制。下面代码说明了之前的异常处理方式:

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

}

当调用一个可能失败的方法时,可以传给它一个NSError对象,如果出现异常,这个对象会被赋予相应的错误值,通过判断它是否为nil就可以进行相应的处理。

注意:NSURLConnection.sendSynchronousRequest() 已经在IOS9中被弃用,由于大多数读者更加熟悉这个用法,在此仅进行举例。

try / throw / catch

在Swift2中,采用以try-catch-throw为关键字的异常处理模型,上面的代码就会变成这样:

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)

}


现在你可以使用do-catch语句来捕获异常并且进行相应的处理。在调用的方法前采用try关键字。在Swift2中,在我们调用一个抛出异常的方法时,我们需要使用try关键字。那如何判断一个方法抛出了异常呢?当你在编辑器中输入方法时,抛出异常的方法会用throws关键字标识。

Swift2.新特性_第1张图片
那方法是如何抛出异常的呢?
假设现在有一个汽车发动机模型,在下面条件下,发动机启动失败:

  • No fuel
  • Oil leakage
  • Low battery

在Swift中,异常类型需要实现ErrorType协议,在这个例子中,你可以定义一个实现ErrorType的枚举类型:

enum CarEngineErrors: ErrorType {

case NoFuel

case OilLeak

case LowBattery 

}

接着,生成一个可以抛出异常的方法,在声明中用throws关键字:
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

}

}

调用checkEngine方法时,需要在前面加上try关键字:
func startEngine(){

try checkEngine()

}

如果你将上述代码在Playgrounds运行时,会报错,原因是没有进行异常处理,Swift里的异常处理机制要求需要用do-catch语句捕获所有的异常并进行处理。
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!")

}

类似于switch语句,在Swift2中你需要处理每种可能出现的异常。

6.defer

在Java中,有一个类似的异常处理机制try-catch-finally无论是否存在异常finally中的语句都会执行。
Swift2通过defer关键字提供了相似的语句,无论是否存在异常,defer中的语句在当前范围运行结束时都会得到执行,继续用上面的例子,将checkEngine()作如下修改:

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

}

}

然后运行startEngine()方法,此时在playgrounds得到的结果:

Low Battery!
this is the defer statement

defer语句尤其可以应用于清空操作:

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

}

7.协议扩展

在Swift1.2中,你可以使用扩展现有的类、结构体或者枚举,Swift2还允许扩展协议类型。通过协议扩展,你可以给协议添加方法和属性。下面是协议扩展的一个例子。

定义一个Awesome的协议:

protocol Awesome {

func awesomenessPercentage() -> Float

}

定义两个实现Awesome协议的类:
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()

}

在Playgrounds上运行上述代码,你可以看到如下输出:

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

extension Awesome {

var awesomenessIndex: Int {

get{

return Int(awesomenessPercentage() * 100)

}

}

}

通过扩展协议,所以实现协议的类就可以使用协议的awesomenessIndex属性。


Swift2.新特性_第2张图片

8.Availability 检查

当在多个IOS版本下开发开发APP时,会使用最新版本的API接口,这使得在老的版本下运行时会出现异常。在Swift2之前,并没有相应的检查。NSURLQueryItem类仅能在不低于IOS8的版本下使用,如果在之前的版本使用就会倒是异常或程序崩溃,为了避免异常你可能会这样进行检查:

if NSClassFromString("NSURLQueryItem") != nil {

// iOS 8 or up

} else{

// Earlier iOS versions

}

但是从Swift2之后,有了相应的API的可用性检查,如下所示:
@available(iOS 9, *)

class SuperFancy {

// implementation

}

可以在if语句中使用#avaliable关键字,表示能够支持的最低版本,当然也可以使用guard代替if*:
guard #available(iOS 8.4, OS X 10.10, *) else {

// what to do if it doesn't meet the minimum OS requirement

return

}

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

你可能感兴趣的:(Swift2.新特性)