在
Swift中,我可以使用ARC机制来管理进程外部资源的生命周期,因为类的实例可以预先解除初始化.这与Java Runtime之类的环境形成对比,在Java Runtime中,当垃圾收集器收集对象时,实例被去初始化,这不能保证在定义的时间窗口中发生.
但是,当局部变量引用这些实例时,Swift语言和运行时对实例生命周期的确切保证是什么?例如.当局部变量持有对它的唯一引用时,实例可能被释放的最早点是什么?
在下面的示例中,我创建了一个类的实例,并在局部变量中存储对它的引用.
public final class Something {
init() { print("something.init()") }
deinit { print("something.deinit()") }
}
func useSomething() {
let something = Something()
print("useSomething()")
}
useSomething()
在我打印useSomething()之后不使用该变量,但是在调用print()之后deinit运行一致:
$swift run -c release
something.init()
useSomething()
something.deinit()
似乎引用总是在变量超出范围时递减.在do块中包装变量声明会更改顺序:
func useSomething() {
do { let something = Something() }
print("useSomething()")
}
$swift run -c release
something.init()
something.deinit()
useSomething()
这个订单是保证还是可以用不同的编译器或优化级别更改?
我对此感兴趣的原因是我想在面向对象的Swift API中包装C API,并希望使用Swift类和引用计数自动管理使用C API分配的资源的生命周期.如果C API的每次使用都需要对其操作的资源的引用,那么这很有用,因为我知道Swift实例将至少存活到对实例所代表的资源进行操作的最后一次调用.
但是一些API使用全局状态来选择资源,并且对API的后续调用不需要引用要传递的资源,而是隐式地对所选资源进行操作. OpenGL的glDrawElements()隐式使用5或10个这样的资源(顶点数组,着色器,帧缓冲区,纹理……).