Swift 3 新特性
前言如果你最近没有跟进Swift Evolution的步伐,你也许会问到底有啥变化,它会怎样影响你的代码,以及你什么时候应该迁移到Swift 3上来。那么这篇文章会为你一一解答。
开始现在Swift 3预览版已经可以在Xcode 8 beta版使用了。尽管Swift 3的进化之路就要接近尾声,但是在接下来的几个月还是会做出一些变化。Swift 3的特性最终确定下来是在2016年,Xcode 8 正式版本发布的时候,所以你不得不推迟采用Swift 3编写的 App的发布日期。 为了让开发者能够按照他们自己的方式迁移到Swift 3上来,作为一个小的升级包,Xcode 8会包含Swift 2.3。从开发者的角度看,Swift 2.3跟Swift 2.2是一样的,只不过它会支持更多新的SDKs和WWDC上宣布的Xcode新特性。一旦Xcode 8 发布正式版,且你还没有迁移到Swift 3上来,那么你可以提交用Swift 2.3编写的App。 我建议你在playground中测试我们要讨论的特性,还有你也许可以在你的一个工程里运行迁移助手(还是不要拿公司项目做小白鼠了?),来感受一下新技术带来的变化。因为直到Xcode 8 正式版发布,Swift 3最终确定下来,你才能发布app,所以你该考虑等到所有事情有了定论再迁移到Swift 3上来。 迁移到Swift 3当转换到Swift 3,你会发现几乎所有文件都需要改变!这主要是因为Cocoa API命名发生了改变。或者更准确的说,API相同的,但是现在OC,Swift的命名不统一。Swift 想要在接下来的时间让Swift的书写更加自然。 苹果在Xcode 8 中集成了迁移助手,它可以智能地帮助你修正这些变化。但是不要惊讶,如果你想要自行修改一下地方,那么迁移助手是不会自动帮你处理的。 你可以很快地转换到Swift 2.3 或者 Swift 3上来。如果你想转换回来,你可以在Xcode这么操作:Edit > Convert > To Current Swift Syntax ... 。编译器像迁移助手一样智能,如果你在一个方法的调用上使用了旧的API,编译器会提供一个可选选项帮助你修正,这样你就能使用正确的现代的API了。 最重要的消息是:Swift 3目标是成为做出重大变化的最后一个版本。所以当Swift从一个版本迭代到另一个版本时,你能够保持自己的代码不变。尽管Swift 核心团队不能预测未来,但是他们承诺如果真的需要破坏源兼容性,他们会提供一个相当长的废弃周期。那就意味着Swift语言具有了源稳定性,这会促进更多保守公司采用Swift语言。 据说,二进制稳定性的目标还没有实现。在文章结尾,你会了解更多二进制稳定性的影响。 已经实现的---Swift进化提议自从Swift开源,社区成员对于Swift的改变,给出了上百条提议。大多数提议(目前70条,或者更多)在讨论后都被接受了。那些被拒的提议也是在经过激烈的讨论后,做出的决定。无论如何,最终Swift核心团队会对所有的提议做出决定。 Swift核心团队与社区展开了广泛的互动交流。事实上,Swift在Github上获得了3万多颗星。日复一日,每周都有好几条提议被提出。甚至苹果的工程师想要做出改变时,也会在Github开出新的仓库,给出提议。 在以下部分,你会看到诸如[SE-0001]的标签。这些是是Swift Evolution 提议编号。这里的有编号的提议都是已被接受,会在Swift 3中实现。同时也会提供每一个提议的链接,你可以查看每一个改变的具体细节。 API 变化Swift 3最大的更新是标准库采用了统一的命名规范。API 设计指南包含了团队构建Swift 3遵守的规范,这对于编写可读性,易维护性代码具有很重的价值。核心团队实践这样的准则:好的API设计总是考虑到调用场景。他们努力让API的用途变得更加清晰。废话不多说了,接下来是最有可能影响到你的变化。 第一个参数标签我们以一个我们每天都在使用的实例开始。 函数和方法中的第一个参数会需要一个便签,除非你有其他方面的需求。之前,当你调用一个函数或者方法时,你是省略第一个参数标签的[SE-0046]: //第一条为Swift 2中旧的方式, 下一条是Swift 3中新的方式 ?
注意方法定义是怎么为外部名称使用诸如:"of","to","with",和 "in"等介词的。 tableView(_ tableView: UITableView,numberOfRowsInSection section: Int) -> Int { ... }
在很多编程语言中,方法会有一个基础的名字并提供不同的参数名。Swift也不例外,现在你会经常碰到重载方法,因为API更加直接。这里有一个例子,表现index()方法的两种形式: let names = ["Anna","Barbara"] ?
if let annaIndex = names.index(of: "Anna") { ?
? ?print("Barbara's position: (names.index(after: annaIndex))") ?
}
总之,参数名的变化让方法名更加统一,也更加容易学习。 省略不必要的单词在之前的苹果库的版本迭代中,方法会包括一个名字,用来指示返回值。得益于Swift编译器的类型检查,这显得不是很必须。团队认真审视后过滤掉了这些噪音只留下信号,结果很多重复的单词都被移除了。 API在OC库转换到原生Swift方面更加智能 [SE-0005]: //第一条为Swift 2中旧的方式, 下一条是Swift 3中新的方式 ?
现代化 GCD 和 Core Graphics说到对旧的API的反对,GCD和Core Graphics成了最需要被改造的两个。 GCD用在多线程任务中,例如:耗时的计算工作或者与服务器的通信。通过切换任务到不同的线程,可以避免阻塞用户线程。libdispatch库是用C语言写的,而且采用C语言风格的API。现在这些API被以原生Swift的风格重新设计。 // Swift 2 旧方式 ?
相似的,Core Graphics 也是用C写的,过去使用了非常糟心的函数调用。可以看一下新方法的样子[SE-0044]: // ?Swift 2 旧方法 ?
枚举 Cases 首字母另一个与你已经习惯的Swift编码方式不同是,枚举case 现在使用lowerCamelCase。这会让他们与其他属性更加一致 - [SE-0006]: //第一条为Swift 2中旧的方式, 下一条是Swift 3中新的方式 ?
UpperCamelCase现在只在类型名和协议名上有保留。这可能要花上一段时间来适应,但是Swift团队这么做有他的理由---他们在努力达成一致性。 有返回值的函数和修改自身的函数Swift标准库在用名词,动词的函数命名会越来越统一。你依据动作发生带来的影响来命名一个函数。经验法则是:如果它包含一个像"-ed" 或者"-ing"的后缀,那么认为这是一个名词函数。名词函数会返回一个值。如果它没有后缀,那么它很可能是一个必要的动词。这些"动词"函数在引用内存执行动作。这也被称为modifying in place。以下是遵守名词/动词规则的函数对。这里还有一些函数对[SE-0006]: customArray.enumerate() ? customArray.enumerated() ? customArray.reverse() ? customArray.reversed() ? customArray.sort() // changed from .sortInPlace() ? customArray.sorted()
这里是一些行为上差异: var ages = [21,255);">10,255);">2] //变量,可以修改 ?
函数类型函数声明和函数调用总是需要括号包括参数: f(a: Int) { ... } ?
f(5)
然而,当你用函数类型作为参数时,你可能会这么写: g(a: Int -> Int) -> Int->Int { ... }//swift 2中旧方法
你可能注意到这非常难读。参数在哪里结束?返回值在哪里开始?在Swift 3中正确的定义这个函数是 [SE-0066]: g(a:(Int) -> Int) -> (Int) -> //swift 3 新方法
现在的参数列表是括号包围,随后是返回类型。这样函数变得更加清晰,结果是,函数类型变得更容易识别。
//swift 2中旧方法 ?
新增API尽管Swift 3最大的更新是对现存API的修改,但是Swift社区也在添加新的API方面,做了大量的工作。 获取包含类型(或者说是隐含类型)当你定义一个静态属性或者方法时,你总是通过类型直接调用他们: CustomStruct.StaticMethod()
如果你在一个类型的中编写代码,你还需要一个类型名来调用静态方法。为了更加清晰,现在你可以调用Self来获取隐含类型。大写字母"S"获得self的类型,小写字母"s"获取self的实例。 这里会解释工作原理[SE-0068]: struct CustomStruct { ?
? ?static staticMethod() {} ?
? ?instanceMethod() { ?
? ? ? ?Self.staticMethod() //在类型体内部,之前要写成CustomStruct.staticMethod() ?
? ?} ?
} ?
let customStruct = CustomStruct() ?
customStruct.Self.staticMethod()
内联序列sequence(first: next:)和sequence(state: next:)是全局函数他们返回无限序列。你可以给他们一个初始值,或者初始状态,他们会以懒加载的方式应用到一个闭包[SE-0094]: for view in sequence(first: someView,next: {$0.superView}) { ?
? ? ? //someView,someView.superView,someView.superView.superView,... ? }
你可以通过添加前缀操作符,来限制序列 for x in sequece(first: 0.1,255);">0 * 2}).prefix(while:{$0 < 4}) { ?
? ? ? //0.1,0.2,0.4,0.8,1.6,3.2 ? }
其他零碎的变化
工具上的提升Swift是一门语言,编写Swift代码要用到开发环境-苹果开发者就是Xcode了!工具的变化将会影响到你每天怎么编写代码。
Xcode正在学习以原生Swift的方式进行思考:
Swift快照像是Swift Evolution的后续版本。在完全集成进Xcode前,他们提供一 个机会来使用新的语法。Xcode 8可以在Playground中加载并运行Swift快照。 Swift包管理器Swift源码实际上是几个仓库的集合,包括:语言,核心库,还有包管理器。此套件一起构成了我们所认识的Swift。 Swift包管理器为你的分享代码和工程代码定义了一个简单的目录结构。
预计未来的特性之前提到过,Swift 3 通过避免重大变化,让你能够在Swift版本迭代中保持你的代码。但是事实上,一些崇高的目标还有没有达到,即泛型添加和ABI稳定。 ABI稳定允许不同版本的Swift应用,库一起编译,链接,和相互通信。ABI稳定对于第三方库不提供源码情况下组装框架至关重要,因为Swift新版本要求他们不仅要更新代码,还要重新构建框架。
所以总而言之,你可以在Swift版本迭代中保持你的源码,但是版本之间,编译后的二进制文件的兼容问题还没有解决。 总结随着社区的不断实践,Swift持续发展。虽然还在起步阶段,但是这门语言有很大动力和明朗的未来。Swift已经运行在Linux上了,而且在未来几年内,你很有可能看到它运行在服务器端。从头设计一门语言有它的优势,一旦ABI稳定下来,想要再打破它的可能性会非常小。现在正是更正语言的好机会,绝不后悔。(哈,swift 3是多么被寄予厚望呀! (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |