swift - 在涉及 NSHashTable 的特殊情况下不调用 deinit

标签 swift automatic-ref-counting weak-references deinit

<分区>

我发现了一些奇特有趣的东西,很想听听任何人的意见。因此,首先让我们采用类的这个定义:

class TestClass:NSObject {  
    var s1 = NSHashTable<TestClass>(options: .weakMemory)  

    func doit(bla:TestClass) {  
        s1.add(bla)  
        bla.s1.add(self)  
    }  

    deinit {  
        print("Deinit")  
    }  
}  

现在让我们考虑以下问题:

var t1:TestClass? = TestClass()  
var t2:TestClass? = TestClass()  

如果我们做了以下 deinit 被调用:

t1?.s1.add(t2!)  
t2?.s1.add(t1!)  

t1 = nil // This will result in deinit being called  

现在让我们做同样的事情,但是调用 doit() 方法

t1?.doit(bla:t2!)  

t1 = nil // Deinit doesn't get called for some reason  

这里的问题是为什么在这种情况下不调用 deinit?这有什么不同,因为它本质上具有与第一种方法相同的引用分配?

我很乐意听取任何人对此的意见。

最佳答案

像往常一样,问题是您正试图在 Playground 上测试这个。不。 Playground 是魔鬼的杰作。

在实际的应用程序项目中测试,您会看到调用了deinit

示例(iOS,但 macOS 中的等效项也可以):

import UIKit

class TestClass:NSObject {
    var s1 = NSHashTable<TestClass>(options: .weakMemory)
    func doit(bla:TestClass) {
        s1.add(bla)
        bla.s1.add(self)
    }
    deinit {
        print("Deinit")
    }
}

class ViewController: UIViewController {
    var t1:TestClass? = TestClass()
    var t2:TestClass? = TestClass()

    override func viewDidLoad() {
        super.viewDidLoad()
        t1?.doit(bla:t2!)
        t1 = nil // --> "Deinit"
        print(t2?.s1) // --> it's empty
    }
}

关于swift - 在涉及 NSHashTable 的特殊情况下不调用 deinit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42547918/

相关文章:

ios - NSURLConnection 消耗大量内存

objective-c - ARC 和 CFRelease?

ios - 作为iVar的weakSelf

c++ - 如何在 C++ 中维护指向父对象的弱指针?

ios - 触摸开始不被召唤

swift - 当我在 Swift 中使用 UITabbar 时,不可能隐藏状态背景

IOS : NSArray of CFUUIDRef

objective-c - 如何测试 Objective-C 对象是否可以在 ARC 下使用弱引用?

swift - 一堆 if 语句作为函数以及如何在 swift 中调用它

swift - 在子类化 NSURLSession Swift 时,初始化程序不会覆盖指定的初始化程序