浙江易网科技股份有限公司

Swift 2.0初探:值得注意的新特性

2015-11-07 10:11:31 来源: 浙江易网科技股份有限公司(杭州)

转眼间,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努力将更快、更安全做到极致,这是开发人员的福音,让我们尽情享受这门美妙的语言吧。


您给我们信任,我们给您惊喜!
易网10年对大数据技术和行业趋势的深入洞察和积淀后,结合中国企业的实际情况和特色,已经探索出了一条商业智能可持续发展之路,形成了成熟的中国“平台一体,智慧应用”的产业推进模式。
一向本着稳健的原则开拓与绝对领先的研发实力,保证公司在行业内的市场信用度和企业形象,使得公司能够在智能科技领域保持领先地位。
联系 Contact
057188848892
传真:057187157782
邮箱:webmaster@eoner.com
地址:浙江省杭州市西湖区双龙街199号金色西溪商务中心1号楼1至2层
留言 Message
Copyright © 2012 The things 浙江易网科技股份有限公司 make. All rights reserved. 浙ICP备09052236号-7
茂名资讯网 网站名称 易搜网 网站名称 网站名称 小白熊官网 网站名称 网站名称 网站名称 青岛昊宇石业
988棋牌 浙江易网科技股份有限公司福建泰顺棋牌俱乐部 上海时时乐 吉林快3 安徽快3 内蒙古快3计划 福建快3 浙江易网科技股份有限公司福建11选5 湖南快乐十分 北京两步彩 智慧彩票 山东群英会app 新疆喜乐彩 浙江易网科技股份有限公司乐彩网 海南4+1走势图 河南快3走势图 天津快乐十分走势图 浙江易网科技股份有限公司陕西快乐十分走势图 浙江易网科技股份有限公司500万彩票 秒速时时彩 天津11选5走势图 天津11选5走势图 天津11选5走势图 天津11选5 天津快乐十分 天津快乐十分 天津快乐十分 浙江易网科技股份有限公司天津快乐十分 河北11选5 浙江易网科技股份有限公司河北11选5 河北11选5官网 河北11选5官网 河北11选5 吉林快3走势图 吉林快3 吉林快3官网 吉林快3 广西快3 广西快3 广西快3平台 贵州快3 贵州快3 甘肃快3 甘肃快3 甘肃快3 甘肃快3 甘肃11选5 甘肃11选5 甘肃11选5 湖南快乐十分官网 四川11选5 四川11选5 博狗手机版 博狗 博狗 上海天天彩选4 山东十一运夺金 山东十一运夺金 山东十一运夺金 六合宝典 大神棋牌 大神棋牌 大神棋牌注册 盛京棋牌 浙江易网科技股份有限公司波克棋牌 波克棋牌 波克棋牌 吉祥棋牌 吉祥棋牌官网 青龙棋牌下载 青龙棋牌游戏 青龙棋牌下载 青龙棋牌下载 星空棋牌 星空棋牌 同城棋牌 同城棋牌官网 浙江易网科技股份有限公司同城棋牌 54棋牌游戏 54棋牌官网 54棋牌官网 54棋牌 54棋牌 7080棋牌 爱乐棋牌 爱乐棋牌 88棋牌 88棋牌 老K棋牌 老K棋牌 海南4+1 智慧彩票 途游棋牌 途游棋牌 浙江易网科技股份有限公司91棋牌APP 91棋牌官网 零点棋牌 零点棋牌 众博棋牌 众博棋牌官网 众博棋牌 宝博棋牌 988棋牌