默认情况下,Swift 对象的生命周期如下:
在 WWDC 21 中 ARC in Swift: Basics and beyond,新发布的 Xcode 13 增加了一个选项,用来优化 Swift 对象的生命周期:
当这个选项开启后,对象原本要超出作用域才会析构,现在被优化为在作用域内不再被使用就会被析构。 这个特性是在编译期间进行的,由编译器在适当的地方插入 release 来提前结束对象的生命周期。
class Configuration {
deinit {
print("Configuration - deinit")
}
}
func test() {
print("start")
let c = Configuration()
print("end")
}
当 Optimize Object Lifetimes: YES
的时候,日志输出的顺序如下:
start
Configuration - deinit
end
可以发现,当在对象不再被使用的时候,就被析构了。这样做的好处是可以及时释放内存。当然也会带来一些额外的问题,如何写代码来避免这些问题在 WWDC 的视频中阐述的很清楚了。
当不开启这个特性 Optimize Object Lifetimes: NO
的时候,日志输出的顺序如下:
start
end
Configuration - deinit
在 WWDC 视频的最后,Apple 开发人员建议大家开启 Optimize Object Lifetimes
。
值得注意的是,需要在 Release
模式,即打开优化后才会生效。
在 Debug
,即无优化的情况下,即使开启了 Optimize Object Lifetimes
,对象也是超出作用域才会析构。
在测试中发现,在 Optimize Object Lifetimes
后,let
和 var
修饰的变量的生命周期并不一样,var
修饰的变量在不被使用的时候就会被释放,而 let
修饰的变量则直到超出作用域才被释放。
如果是使用命令编译 Swift 源码,对应的编译参数是:swiftc -Xfrontend -enable-copy-propagation
。
Swift Package Manager 中:swift build -c release -Xswiftc -Xfrontend -Xswiftc -enable-copy-propagation
。
相关的讨论: https://forums.swift.org/t/why-are-let-and-var-variable-lifetimes-different/56338
Xcode 14 和 Swift 5.7
https://developer.apple.com/documentation/xcode-release-notes/xcode-14-release-notes
Xcode 13 provided a Swift build setting called “Optimize Object Lifetimes” that’s not available in Xcode 14. If your project already customized this build setting, it now becomes a user-defined setting. It has no effect and you can remove it. Xcode 14 now consistently optimizes object lifetimes. (91971848)
在 Xcode 14 中(内置 Swift 5.7),这个特性已经被移除了。