我只是在玩弄漏洞,并试图故意制造一个漏洞。所以,即使这样做是愚蠢的:
class LeakingObjectA{
var strongRefToB:LeakingObjectB?
deinit{ print("LeakingObjectA deinit")}
}
class LeakingObjectB{
var strongRefToA:LeakingObjectA?
deinit{ print("LeakingObjectB deinit")}
}
这对于科学目的来说很好,并且这会创建一个强大的引用循环。
现在在 didMoveToView
中,我声明局部常量并像这样进行泄漏:
override func didMoveToView(view: SKView) {
let a = LeakingObjectA()
let b = LeakingObjectB()
a.strongRefToB = b
b.strongRefToA = a
}
转换到另一个场景后,场景的 deinit
被正确调用,但是 deinits
来自 a
和 b
实例并未实际调用。
我还说泄漏,因为这实际上在仪器中被检测为泄漏:
现在,如果我将这两个局部变量声明为场景的属性,那么 Instruments 检测到的泄漏会有所不同:
class GameScene:SKScene {
let a = LeakingObjectA()
let b = LeakingObjectB()
//...later in didMoveToView method I make a strong reference cycle like from the example above
}
当然在这种情况下,场景的deinit
在转换后也会被调用,和上面一样,deinits
来自a
和b
实例没有被调用(因为强引用循环)。
不过,这在 Instruments 中未被检测为泄漏...那么对此的合理解释是什么?
最佳答案
我无法使用下面的代码复制它。临时场景已正确取消初始化,并且 LeakingObjectA
和 LeakingObjectB
都出现在泄漏工具中。
class LeakingObjectA {
var strongRefToB:LeakingObjectB?
deinit{ print("LeakingObjectA deinit")}
}
class LeakingObjectB {
var strongRefToA:LeakingObjectA?
deinit{ print("LeakingObjectB deinit")}
}
class TempScene : SKScene {
let a = LeakingObjectA()
let b = LeakingObjectB()
override init() {
a.strongRefToB = b
b.strongRefToA = a
super.init(size: CGSizeZero)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
print("Deiniting temp scene")
}
}
class ViewController {
var tempScene: TempScene?
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
tempScene = TempScene()
}
override func viewWillDisappear(animated: Bool) {
super.viewWillDisappear(animated)
tempScene = nil
}
}
关于ios - 在两个局部变量之间的仪器中检测到泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36184207/