您的位置:首页 > 移动开发 > Swift

Swift 2.0初探

2015-11-12 15:51 423 查看
转眼间,Swift已经一岁多了,这门新鲜、语法时尚、类型安全、执行速度更快的语言已经渐渐的深入广大开发者的心。

今年6月,一年一度的WWDC大会如期而至,在大会上Apple发布了Swift 2.0,引入了很多新的特性,以帮助开发者能更快,更简单的构建应用。我在这里也说道说道Swift 2.0中值得大家注意的新特性。

guard
语句

guard
语句和
if
语句有点类似,都是根据其关键字之后的表达式的布尔值决定下一步执行什么。但与
if
语句不同的是,
guard
语句只会有一个代码块,不像
if
语句可以
if else
多个代码块。

那么
guard
语句的作用到底是什么呢?顾名思义,就是守护。
guard
语句判断其后的表达式布尔值为
false
时,才会执行之后代码块里的代码,如果为
true
,则跳过整个
guard
语句,我们举例来看看。

我们以今年高考为例,在进入考场时一般都会检查身份证和准考证,我们写这样一个方法:

func checkup(person: [String: String!]) {

// 检查身份证,如果身份证没带,则不能进入考场
guard let id = person["id"] else {
print("没有身份证,不能进入考场!")
return
}

// 检查准考证,如果准考证没带,则不能进入考场
guard let examNumber = person["examNumber"] else {
print("没有准考证,不能进入考场!")
return
}

// 身份证和准考证齐全,方可进入考场
print("您的身份证号为:\(id),准考证号为:\(examNumber)。请进入考场!")

}

checkup(["id": "123456"]) // 没有准考证,不能进入考场!
checkup(["examNumber": "654321"]) // 没有身份证,不能进入考场!
checkup(["id": "123456", "examNumber": "654321"]) // 您的身份证号为:123456,准考证号为:654321。请进入考场!


上述代码中的第一个
guard
语句用于检查身份证,如果检查到身份证没带,也就是表达式为
false
时,执行大括号里的代码,并返回。第二个
guard
语句则检查准考证。

如果两证齐全,则执行最后一个打印语句,上面的两个
guard
语句大括号内的代码都不会执行,因为他们表达式的布尔值都是
true


这里值得注意的是,
id
examNumber
可以在
guard
语句之外使用,也就是说当
guard
对其表达式进行验证后,
id
examNumber
可在整个方法的作用域中使用,并且是解包后的。

我们再用
if else
语句写一个类似的方法:

func checkupUseIf(person: [String: String!]) {

if let id = person["id"], let examNumber = person["examNumber"] {
print("您的身份证号为:\(id),准考证号为:\(examNumber)。请进入考场!")
} else {
print("证件不齐全,不能进入考场!")
}

print("您的身份证号为:\(id),准考证号为:\(examNumber)")  // 报异常

}

checkupUseIf(["id": "123456"]) // 证件不齐全,不能进入考场!
checkupUseIf(["examNumber": "654321"]) // 证件不齐全,不能进入考场!
checkupUseIf(["id": "123456", "examNumber": "654321"]) // 您的身份证号为:123456,准考证号为:654321。请进入考场!


我们可以看到用
if else
实现的方法显然不如
guard
实现的那么精准。而且
id
examNumber
的作用域只限在
if
的第一个大括号内,超出这个作用域编译就会报错。

通过上述两个小例子不难看出,
guard
语句正如一个称职的守卫,层层把关,严防一切不允许发生的事,并且让代码具有更高的可读性,非常棒。

异常处理

在Swift 1.0时代是没有异常处理和抛出机制的,如果要处理异常,要么使用
if else
语句或
switch
语句判断处理,要么使用闭包形式的回调函数处理,再要么就使用
NSError
处理。以上这些方法都不能像Java中的
try catch
异常控制语句那样行如流水、从容不迫的处理异常,而且也会降低代码的可读性。当Swift 2.0到来后,一切都不一样了。

在Swift 2.0中Apple提供了使用
throws
throw
try
do
catch
这五个关键字组成的异常控制处理机制。下面我们来举例看看如何使用,我用使用手机刷朋友圈为例。

首先我们需要定义异常枚举,在Swift 2.0中Apple提供了
ErrorType
协议需要我们自定义的异常枚举遵循:

enum WechatError: ErrorType {
case NoBattery // 手机没电
case NoNetwork // 手机没网
case NoDataStream // 手机没有流量
}


我们定义了导致不能刷微信的错误枚举
’wechatError
。然后定义一个检查是否可以刷微信的方法
checkIsWechatOk()


func checkIsWechatOk(isPhoneHasBattery: Bool, isPhoneHasNetwork: Bool, dataStream: Int) throws {

guard isPhoneHasBattery else {
throw WechatError.NoBattery
}

guard isPhoneHasNetwork else {
throw WechatError.NoNetwork
}

guard dataStream > 50 else {
throw WechatError.NoDataStream
}

}


这里注意,在方法名后有
throws
关键字,意思为该方法产生的异常向上层抛出。在方法体内使用
guard
语句对各种状态进行判断,然后使用
throw
关键字抛出对应的异常。然后我们定义刷微信的方法:

func playWechat(isPhoneHasBattery: Bool, isPhoneHasNetwork: Bool, dataStream: Int) {

do {
try checkIsWechatOk(isPhoneHasBattery, isPhoneHasNetwork: isPhoneHasNetwork, dataStream: dataStream)
print("放心刷,刷到天昏地暗!")
} catch WechatError.NoBattery {
print("手机都没电,刷个鬼啊!")
} catch WechatError.NoNetwork {
print("没有网络哎,洗洗玩单机吧!")
} catch WechatError.NoDataStream {
print("没有流量了,去蹭Wifi吧!")
} catch {
print("见鬼了!")
}

}

playWechat(true, isPhoneHasNetwork: true, dataStream: 60) // 放心刷,刷到天昏地暗!
playWechat(true, isPhoneHasNetwork: false, dataStream: 60) // 没有网络哎,洗洗玩单机吧!
playWechat(false, isPhoneHasNetwork: true, dataStream: 60) // 手机都没电,刷个鬼啊!
playWechat(true, isPhoneHasNetwork: true, dataStream: 30) // 没有流量了,去蹭Wifi吧!


上述的代码示例中,首先检查是否可以刷微信的方法前使用
try
关键字,表示允许该方法抛出异常,然后使用了
do catch
控制语句捕获抛出的异常,进而做相关的逻辑处理。

这套异常处理机制使Swift更加的全面和安全,并且提高了代码的可读性,非常棒。

协议扩展

在Swift 1.0 时代,协议(
Protocol
)基本上类似一个接口,定义若干属性和方法,供类、结构体、枚举遵循和实现。在Swift 2.0中,可以对协议进行属性或者方法的扩展,和扩展类与结构体类似。这让我们开启了面向协议编程的篇章。

Swift中,大多数基础对象都遵循了
CustomStringConvertible
协议,比如
Array
Dictionary
(Swift 1.0中的
Printable
协议),该协议定义了
description
方法,用于
print
方法打印对象。现在我们对该协议扩展一个方法,让其打印出大写的内容:

var arr = ["hello", "world"]
print(arr.description) // "[hello, world]"

extension CustomStringConvertible {
var upperDescription: String {
return "\(self.description.uppercaseString)"
}
}

print(arr.upperDescription) // "[HELLO, WORLD]"


如果在Swfit 1.0时代,要想达到上述示例的效果,那么我们需要分别对
Array
Dictionary
进行扩展,所以协议的扩展极大的提高了我们的编程效率,也同样使代码更简洁和易读。

打印语句的改变

在Swift1中,有’println()’和’print()’两个在控制台打印语句的方法,前者是换行打印,后者是连行打印。在Swift2中,’println()’已成为过去,取而代之的是他俩的结合体。如果你想做换行打印,现在需要这样写:

print("我要换行!", appendNewline: true)


available
检查

作为iOS开发者,谁都希望使用最新版本iOS的Api进行开发,省事省力。但常常事与愿违,因为我们经常需要适配老版本的iOS,这就会面临一个问题,一些新特性特性或一些类无法在老版本的iOS中使用,所以在编码过程中经常会对iOS的版本做以判断,就像这样:

if NSClassFromString("NSURLQueryItem") != nil {
// iOS 8或更高版本
} else{
// iOS8之前的版本
}


以上这只是一种方式,在Swift 2.0之前也没有一个标准的模式或机制帮助开发者判断iOS版本,而且容易出现疏漏。在Swift 2.0到来后,我们有了标准的方式来做这个工作:

if #available(iOS 8, *) {
// iOS 8或更高版本
let queryItem = NSURLQueryItem()

} else {
// iOS8之前的版本

}


这个特性让我们太幸福。

do-while
语句重命名

经典的
do-while
语句改名了,改为了
repeat-while


var i = 0
repeat {
i++
print(i)
} while i < 10


个人感觉更加直观了。

defer
关键字

在一些语言中,有
try/finally
这样的控制语句,比如Java。这种语句可以让我们在
finally
代码块中执行必须要执行的代码,不管之前怎样的兴风作浪。在Swift 2.0中,Apple提供了
defer
关键字,让我们可以实现同样的效果。

func checkSomething() {

print("CheckPoint 1")
doSomething()
print("CheckPoint 4")

}

func doSomething() {

print("CheckPoint 2")
defer {
print("Clean up here")
}
print("CheckPoint 3")

}

checkSomething() // CheckPoint 1, CheckPoint 2, CheckPoint 3, Clean up here, CheckPoint 4


上述示例可以看到,在打印出“CheckPoint 2”之后并没有打印出“Clean up here”,而是“CheckPoint 3”,这就是
defer
的作用,它对进行了
print("Clean up here")
延迟。我们再来看一个I/O的示例:

// 伪代码
func writeSomething() {

let file = OpenFile()

let ioStatus = fetchIOStatus()
guard ioStatus != "error" else {
return
}
file.write()

closeFile(file)

}


上述示例是一个I/O操作的伪代码,如果获取到的
ioStatus
正常,那么该方法没有问题,如果
ioStatus
取到的是
error
,那么会被
guard
语句抓到执行
return
操作,这样的话
closeFile(file)
就永远都不会执行了,一个严重的Bug就这样产生了。下面我们看看如何用
defer
来解决这个问题:

// 伪代码
func writeSomething() {

let file = OpenFile()
defer {
closeFile(file)
}

let ioStatus = fetchIOStatus()
guard ioStatus != "error" else {
return
}
file.write()

}


我们将
closeFile(file)
放在
defer
代码块里,这样即使
ioStatus
error
,在执行
return
前会先执行
defer
里的代码,这样就保证了不管发生什么,最后都会将文件关闭。

defer
又一个保证我们代码健壮性的特性,我非常喜欢。

Swift 2.0中的新特性当然不止以上这些,但窥一斑可见全豹,Swift 2.0努力将更快、更安全做到极致,这是开发人员的福音,让我们尽情享受这门美妙的语言
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: