Zombie 对象是Objective-C 对象,它们已被释放,但仍接收消息。
在 Objective-C 中,__unsafe_unretained
可用于创建指向不增加引用计数的对象的附加指针。在 Swift 中,这将是unowned(unsafe)
.
这是一个独立的示例:
import Foundation
class MyClass: NSObject {
func foo() { print("foo"); }
deinit { print("deinit") }
}
unowned(unsafe) let obj2: MyClass
do {
let obj1 = MyClass()
obj2 = obj1
print("exit scope")
}
obj2.foo()
obj1
是指向新创建对象的指针,obj2
也是指向同一对象的另一个指针,但不增加引用计数器。当do { ... }
块离开时,对象被释放。通过发送消息给它obj2
会导致僵尸错误:
exit scope
deinit
*** -[ZombieTest.MyClass retain]: message sent to deallocated instance 0x1005748d0
如果您使用Managed
(例如,将指向 Swift 对象的指针转换为 Cvoid
指针以便将它们传递给 C 回调函数)并且您没有选择正确的保留/未保留组合,也会发生这种情况。一个人为的例子是:
let obj2: MyClass
do {
let obj1 = MyClass()
obj2 = Unmanaged.passUnretained(obj1).takeRetainedValue()
print("exit scope")
}
obj2.foo()