我只是在玩泄漏并试图故意创造一个.所以,即使做这样的事情也很愚蠢:
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,但实际上并未调用a和b实例的deinit.
另外我说泄漏,因为这实际上是在仪器中检测到泄漏:
现在,如果我将这两个本地变量声明为场景的属性,则仪器检测到泄漏之间存在差异:
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,并且与上面相同,不会调用a和b实例的deinit(因为强引用循环).
尽管如此,仪器中没有检测到泄漏……那么对此有什么合理的解释呢?
解决方法
我无法使用下面的代码复制此内容.临时场景被正确地取消初始化,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 } }