New Build System
预编译 Bridging Headers 文件
对于 Swift 和 Objective-C 混合的项目,Swift 调用 Objective-C 时,需要建立一个 Bridging Headers 文件,然后把 Swift 要调用的 Objective-C 类的头文件都写在里面,编译器会读取 Bridging Headers 中的头文件,然后生成一个庞大的 Swift 文件,文件内容是这些头文件内的 API 的 Swift 版本。然后编译器会在编译每一个 Swift 文件时,都要编译一遍这个庞大的 Swift 文件的内容。
有了预编译 Bridging Headers 以后,编译器会在预编译阶段把 Bridging Headers 编译一次,然后插入到每个 Swift 文件中,这样就大大提高了编译速度。
苹果宣称 Xcode 9 和 Swift 4 对于 Swift 和 Objective-C 混合编译的速度提高了 40%。
Indexing 可以在编译的同时进行
COW Existential Containers
Swift 4 中为了优化性能引入了 COW Existential Containers,这里的 COW 就代表 “Copy-On-Write”,当存在多个相同的值时,他们会共用 buffer 上的空间,直到某个值被修改时,这个被修改的值才会被拷贝一份并分配内存空间。
移除未调用的协议实现
struct Date { private let secondsSinceReferenceDate: Double } extension Date: Equatable { static func ==(lhs: Date,rhs: Date) -> Bool { return lhs.secondsSinceReferenceDate == rhs.secondsSinceReferenceDate } } extension Date: Comparable { static func <(lhs: Date,rhs: Date) -> Bool { return lhs.secondsSinceReferenceDate < rhs.secondsSinceReferenceDate } }
减少隐式 @objc 自动推断
class MyClass: NSObject { func print() { ... } // 包含隐式的 @objc func show() { ... } // 包含隐式的 @objc }
这样很多并不需要暴露给 Objective-C 也被加上了 @objc。大量 @objc 会导致二进制文件大小的增加。
在 Swift 4 中,隐式 @objc 自动推断只会发生在很少的当必须要使用 @objc 的情况,比如:
复写父类的 Objective-C 方法
符合一个 Objective-C 的协议
其它大多数地方必须手工显示的加上 @objc。
减少了隐式 @objc 自动推断后,Apple Music app 的包大小减少了 5.7%。
Exclusive Access to Memory
例如为 MutableCollection 扩展一个 modifyEach 方法来修改每个元素的值,代码如下:
extension MutableCollection { mutating func modifyEach(_ body: (inout Element) -> ()) { for index in self.indices { body(&self[index]) } } }
假如在调用 modifyEach 时去删除元素:
var numbers = [1,2,3] numbers.modifyEach { element in element *= 2 numbers.removeAll() }
就会在运行时 Crash。
兼容性
Xcode 9 中同时集成了 Swift 3.2 和 Swift 4。 Swift 3.2 完全兼容 Swift 3.1,并会在过时的语法或函数上报告警告。 Swift 3.2 具有 Swift 4 的一些写法,但是性能不如 Swift 4。 Swift 3.2 和 Swift 4 可以混合编译,可以指定一部分模块用 Swift 3.2 编译,一部分用 Swift 4 编译。 迁移到 Swift 4 后能获得 Swift 4 所有的新特性,并且性能比 Swift 3.2 好。 总结:当 Xcode 正式版发布后,现有的 Swift 代码可以直接升级到 Swift 3.2 而不用做任何改动,后续可以再迁移到 Swift 4。或者直接迁移到 Swift 4 也可以,Swift 4 相比 Swift 3 的 API 变化还是不大的,很多第三方库都可以直接用 Swift 4 编译。Swift 1 到 2 和 Swift 2 到 3 的迁移的痛苦在 3 到 4 的迁移上已经大大改善了。