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

转载于:https://www.cnblogs.com/Free-Thinker/p/5151089.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/256020.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 自定义WebView弹窗及屏蔽弹窗

额&#xff0c;还是那个WebView的问题&#xff0c;内核已换成腾讯X5内核&#xff0c;所以接下来的内容会有一些X5内核的方法。但我们的H5是不能改的&#xff0c;还是只有委屈我们自己。先看看H5自带的弹窗 这样子的弹窗在不同的手机上呈现的可能是不同的效果&#xff0c;效果不…

【图像处理】——Python实现two_pass方法来进行连通域的提取

目录 一、相关知识 1、two_pass算法思想 2、并查集算法 二、自定义的two_pass算法

C++ 多线程使用future传递异常

如果 std::async 调用的函数抛出异常&#xff0c;那么这个异常会被存储在值的位置&#xff0c;同时 future 变为 ready ,如果调用 get() 会重新抛出存储的异常。 Note: 标准并没有指定原来的异常对象是被重新抛出或者拷贝后抛出&#xff0c;不同的编译器会做不同的选择。 对于 …

期货黄金与现货黄金比较

现货黄金与期货黄金是目前市场上最热门的黄金投资方式&#xff0c;与国内任何的金融投资品相比&#xff0c;都具有一定的优势。 其实金投网小编觉得现货黄金与期货黄金最主要的不同点是这个&#xff1a;期货黄金做的是国内市场&#xff0c;同股票市场一样&#xff0c;里面有庄家…

DNS域传送漏洞

0x00 相关背景介绍 Dns是整个互联网公司业务的基础&#xff0c;目前越来越多的互联网公司开始自己搭建DNS服务器做解析服务&#xff0c;同时由于DNS服务是基础性服务非常重要&#xff0c;因此很多公司会对DNS服务器进行主备配置而DNS主备之间的数据同步就会用到dns域传送&#…

封装之--通过类中公有方法访问私有成员变量

如何在ClassB中访问ClassA的私有成员变量&#xff1f;&#xff08;典型的封装案例&#xff09; 通过在ClassA中定义公有的成员方法&#xff0c;然后&#xff0c;在ClassB中通过ClassA的对象调用ClassA中的公有方法&#xff0c;来访问ClassA中的私有成员变量。 转载于:https://w…

匹配物镜放大倍数与相机像元尺寸

通常来说&#xff0c;相机内部的CCD或者CMOS传感器上都有感光阵列&#xff0c;由一个一个的感光元件构成&#xff0c;每一个感光元件负责完成光电转换的过程。简单理解&#xff0c;一个感光元件可以认为就是一个像素(pixel)或像元(pel)。像元具有一定尺寸&#xff0c;如果像的尺…

2016/11/10 kettle概述

ETL(Extract-Transform-Load&#xff0c;即抽取&#xff0c;转换&#xff0c;加载)&#xff0c;数据仓库技术&#xff0c;是用来处理将数据从来源&#xff08;以前做的项目&#xff09;经过抽取&#xff0c;转换&#xff0c;加载到达目的端&#xff08;正在做的项目&#xff09…

【深度学习】——非极大值抑制(nms/soft-nms)

目录 一、相关概念 1、iou 1&#xff09;理论计算 2&#xff09;Python代码&#xff08;代码参考yolov3模型util.py文件&#xff09; 2、nms 1)基本思路 2&#xff09;标准nms和soft-nms 3&#xff09;Python代码实现&#xff08;yolov3中util.py文件&#xff0c;增加了…

移动服务安全现状分析!

2019独角兽企业重金招聘Python工程师标准>>> 由于Android开源的环境&#xff0c;导致Android的整体环境都存在很多不安全的因素&#xff0c;同时用户在移动APP客户端的便捷应用&#xff0c;也给用户带来了巨大的安全隐患。未经过移动服务安全加固的APP存在被静态反编…

封装不同类模板的随机数生成器

最近准备刷题&#xff0c;打算简单封装下随机数生成器&#xff0c;方便产生测试数据。C11的STL提供了很多分布类型&#xff0c;我比较常用的是均匀分布&#xff0c;均匀分布的值有两种类型&#xff0c;一类是整数&#xff0c;另一类是浮点数&#xff0c;STL根据值的类型定义了两…

Log4j详细设置说明

1. 动态的改变记录级别和策略&#xff0c;即修改log4j.properties,不需要重启Web应用&#xff0c;这需要在web.xml中设置一下。2. 把log文件定在 /WEB-INF/logs/ 而不需要写绝对路径。3. 可以把log4j.properties和其他properties一起放在/WEB-INF/ &#xff0c;而不是Class-Pat…

【机器学习】——卷积神经网络(Keras)修改学习率(定值+自适应)

目录 1、直接获取现有模型的学习率 2、打印显示学习率 3、调整学习率 1&#xff09;1.LearningRateScheduler 2&#xff09;ReduceLROnPlateau 利用tensorflow的Keras模块我们可以建立我们自己定义的卷积神经网络模型&#xff0c;但是一般不会触碰到学习率这个问题&#x…

使用Docker构建你的第一个服务

1. 感受一下Docker的便捷 项目源码 https://github.com/MoonShining/dockernize-grape-helloworld clone下来以后运行,cd到项目目录下&#xff0c;运行 docker build -t api-sample . docker run -p 8080:8080 api-sample:latest 复制代码就可以访问localhost:8080看到效果了. …

MyEclipse连接MySQL

在官网http://www.mysql.com/downloads/下载数据库连接驱动 本文中使用驱动版本为mysql-connector-java-5.1.40 一、创建一个java测试项目MySQLConnectorsTest 在项目下穿件一个lib文件夹用来存放MySQL驱动包。 右键驱动包build path进行add添加操作&#xff0c;打开Referenced…

在Windows系统中配置Google AddressSanitizer

Google AddressSanitizer简介 AddressSanitizer (ASan) 是 C 和 C 的内存错误检测软件&#xff0c;它可以检测&#xff1a; 释放指针后继续使用堆缓冲区溢出栈缓冲区溢出全局缓冲区溢出返回后继续使用在范围之外继续使用初始化顺序的bug内存泄漏 在 Windows 系统中&#xff…

【剑指offer】——求出一个正整数的质数因子(Python)

目录 一、题目描述 二、思路 1、短除法 2、平方根法 一、题目描述 功能:输入一个正整数&#xff0c;按照从小到大的顺序输出它的所有质因子&#xff08;重复的也要列举&#xff09;&#xff08;如180的质因子为2 2 3 3 5 &#xff09; 最后一个数后面也要有空格 输入描述…

Python字符串笔录

python字符串操作实方法&#xff0c;包括了几乎所有常用的python字符串操作&#xff0c;如字符串的替换、删除、截取、复制、连接、比较、查找、分割等 1、去空格及特殊符号 >>> s 123 >>> s.strip() # 去除所有空格123 >>> s1 123 >>&…

第九周进度条

第六周学习进度条 星期一 星期二 星期三 星期四 星期五 星期六 星期日 所花时间 &#xff08;包括上课&#xff09; 无 上午8:00-9:50 无 无 下午4:00-5:00 下午3&#xff1a;00-5&#xff1a;30 代码量&#xff08;行&#xff09; 0行 260行 0行 0行 0行 0…