Swift 2.0初探
转眼间,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努力将更快、更安全做到极致,这是开发人员的福音,让我们尽情享受这门美妙的语言
Swift 2.0初探的更多相关文章
- Swift 2.0初探:值得注意的新特性
转眼间,Swift已经一岁多了,这门新鲜.语法时尚.类型安全.执行速度更快的语言已经渐渐的深入广大开发者的心.我同样也是非常喜爱这门新的编程语言. 今年6月,一年一度的WWDC大会如期而至,在大会上A ...
- iOS开发系列--Swift 3.0
概述 从写第一篇Swift文章的时候到现在Swift已经从1.2发展到了今天的3.0,这期间由于Swift目前还在发展阶段并不能向下兼容,因此第一篇文章中的部分代码在当前的Xcode环境中已经无法运行 ...
- Swift 3.0 【Swift 3.0 相较于 Swift 2.2 的变化】
一.编译器和语法变化 函数或方法参数 调用函数或方法时从第一个参数开始就必须指定参数名 在Swift的历史版本中出现过在调用函数时不需要指定任何函数参数(或者从第二个参数开始指定参数名),在调用方法时 ...
- Swift 2.x -> Swift 3.0
Swift 3.0 相对于 2.x 有很大变化.特别是因为命名习惯的改变,导致许多 Api 都发生了变化.总的趋势是让表示更简洁. 对旧的代码升级,大部分可以根据提示来进行更正.但也有的需要手动修改. ...
- Swift 2.0 异常处理
转自:http://www.jianshu.com/p/96a7db3fde00 WWDC 2015 宣布了新的 Swift 2.0. 这次重大更新给 Swift 提供了新的异常处理方法.这篇文章会主 ...
- fir.im Weekly - Swift 3.0 的迁移适配指南
无论你是移动开发者,还是桌面端开发者,或者正在IoT领域探索的技术人员,那么应该更加关注 iDev 全平台开发者大会,也许是后半年 iOS 开发者最盛大的技术盛宴.既有知名公司带来专业视野,又有从 S ...
- Swift 3.0首个开发者预览版将在5月12日释出
Swift团队在博客中宣布Swift 3.0语言首个开发者预览版将于5月12日释出,正式版将在4-6周之后推出.开发者预览阶段并无确定的更新周期和计划,不过Swift团队称努力将其控 制在4-6周内. ...
- Swift 3.0 令人兴奋,但Objective-C也有小改进--Objective-C的类属性
由于Swift 3.0 出了太多令人兴奋的新特性,人们很容易忽略 Objective-C中的小改动.或许你会觉得苹果提及Objective-C 很可能是为了提高和Swift互操作性(译者注:互操作性主 ...
- iOS -Swift 3.0 -String(字符串常规用法)
// // ViewController.swift // Swift-String // // Created by luorende on 16/9/10. // Copyright © 2016 ...
随机推荐
- Java异步回调
作者:禅楼望月(http://www.cnblogs.com/yaoyinglong) 1.开始讲故事: 午饭的时候到了,可是天气太冷,根本不想出办公室的门,于是你拨通了某饭店的订餐电话“喂!你好 ...
- SystemTap了解
SystemTrap是监控和跟踪运行中的Linux内核操作的动态方法. http://www.ibm.com/developerworks/cn/linux/l-systemtap/ 使用System ...
- FXForms,自动生成iOS表单
1.简介 FXForms是一个简单的表单提交框架,他的作者是鼎鼎大名的 Nick Lockwood,你也许听说过他的其他的一些框架,比如 iCarousel. 为什么使用FxForms? 表单处理简单 ...
- IOS高级编程之二:IOS的数据存储与IO
一.应用程序沙盒 IOS应用程序职能在系统为该应用所分配的文件区域下读写文件,这个文件区域就是应用程序沙盒.所有的非代码文件如:图片.声音.映象等等都存放在此. 在mac中command+shift+ ...
- linux中$与()的一点使用疑惑解释
a=$(cat 1.sh)等价于a=`cat 1.sh` 而a=(cat 1.sh) 相当于定义一个a数组,内容为cat 1.sha=(`cat 1.sh`)相当于把1.sh里面的内容当成a的数组,a ...
- 转载---CSS3实现曲线阴影和翘边阴影
预备知识 DIV+CSS基础 圆角:border-radius 2D变换:transform:skew && rotate 伪类::before 和 :after 代码 HTML结构代 ...
- Winform开发框架之客户关系管理系统(CRM)的报价单和销售单的处理
在前面介绍了很多CRM相关的界面和实现思路的随笔文章,本篇继续介绍一下系统中用到的一些经验和技巧片段.本篇随笔主要介绍客户关系管理系统(CRM)的报价单和销售单的处理界面效果,使用列表内置的选择代替弹 ...
- 三种对话框的示例(alert,confirm,prompt)
示例代码 <h2>JavaScriptDialog</h2> <hr/> <buttononclick="btn_alert()"> ...
- 关于IIS寄宿WCF服务,客户端不能生成代理类
我在使用VS2010写好WCF的Web服务后,部署在IIS7.0上,可以在IE9上进行访问,并且能显示XML数据,如下图 然后我在项目的客户端进行服务的添加引用,如下图 VS2010自动生成代理类,但 ...
- ASP.NET AJAX Control Toolkit
https://ajaxcontroltoolkit.codeplex.com/ 警告 7 未能找到引用的组件“Antlr3.Runtime”. 警告 6 未能找到引用的组件“HtmlAgilityP ...