让我通过this other question和documentation for ARC中的所有内容来开始我的提问。
我正在尝试使用RAII惯用语来处理问题,并且遇到了一些导致其无法正常工作的不一致之处。
这是一个说明不一致的示例:
class TestClass {
init() {
print("init")
}
deinit {
print("deinit")
}
}
func test() {
TestClass()
defer { print("defer") }
print("end of scope")
}
test()
根据我的c ++经验,我期望TestClass
实例的取消初始化发生在test
函数范围的末尾,这是我想要做的事情。
与此同时,我意识到我正在初始化TestClass
的实例,但没有将其存储在变量中,因此并没有对其的严格引用,因此将其正确地释放是有意义的离开。
因此出现问题是因为项目和游乐场之间的行为不一致。
在操场上,上面的代码产生以下输出:
init
end of scope
defer
deinit // deinit happens at end of scope
after scope
但是在项目中,完全相同的代码会产生不同的结果:
init
deinit // deinit happens immediately
end of scope
defer
after scope
所以
答案 0 :(得分:2)
游乐场对对象进行各种引用,以将其显示在边栏中并预览结果。
您应该认为游乐场的强引用是完全不确定的。对于任何真正的生命周期调试,您都需要在独立程序,库等中运行代码。
答案 1 :(得分:2)
操场不是“真正的Swift”-与常规编译不同,编译器通过插入各种对工具的调用来转换代码。例如,这使您可以查看表达式的计算结果。但是,不幸的是,它可能会改变程序的行为。
但是,值得注意的是,与C和C ++之类的语言不同,Swift不能保证局部变量(或者您的情况是未使用的表达式中的值)在定义它们的作用域结束之前保持有效。优化器可以自由地对其进行早期初始化。
如果要保证示例中SomeClass
的生命周期,可以使用withExtendedLifetime
:
func test() {
withExtendedLifetime(TestClass()) {
defer { print("defer") }
print("end of scope")
}
}