6

我试图弄清楚 NSMapTable 是如何工作的所以我在操场上尝试以下代码:

class Person {
    var name: String


    init(name: String ) {
        self.name = name
        print("\(name) is being initialized")
    }

    deinit {
        print("\(name) is being deinitialized")
    }
}

var hobyePerson : NSMapTable? = NSMapTable<Person, NSMutableString>
(keyOptions: .weakMemory, valueOptions: .weakMemory)

var rob : Person? = Person(name: "Rob Appleseed") // print : Rob Appleseed is being initialized

hobyePerson?.setObject("golf", forKey: rob)
hobyePerson?.count // return : 1


rob = nil // print : Rob Appleseed is being deinitialized
hobyePerson?.count // return : 1 (WHY ???!!!!)

如文档中所写:“键和/或值可以选择“弱”保存,以便在回收对象之一时删除条目。”

为什么即使我初始化了对象,以便在解除分配 rob 时它对键值对具有弱引用,但在 hobyePerson 中仍然有一个元素?

4

2 回答 2

6

NSMapTableweak当您不关心何时释放键/值时,的行为选项效果最佳,而是您确实关心键/值不会被强烈保留,并且在感兴趣的对象变为nil.

为什么这样?

作为基础课程,作者NSMapTable必须平衡功能和性能。

因此,作为性能的“优化”,他们选择了nil不会立即从映射表中删除的弱引用对象......!相反,当它可以有效地完成时,这会“稍后”发生 - 例如当映射表内部调整大小等时。

正如@Luke 在他的回答中提到的那样,有关NSMapTable更多详细信息,请参阅这篇关于对 的行为进行的实验的优秀文章:

http://cocoamine.net/blog/2013/12/13/nsmaptable-and-zeroing-weak-references/

于 2017-10-30T20:09:46.993 回答
2

是的,这是一种奇怪而不幸的行为。本文对此进行了深入探讨。虽然它没有具体探索弱到弱,但描述的行为是相同的。正如该作者所指出的,hobyePerson.keyEnumerator().allObjects.count并且hobyePerson.objectEnumerator().allObjects.count在所有这一切结束时将包含 0 。他还指出,Apple 已经在Mountain Lion 发行说明中记录了这种行为。

然而,目前不推荐弱到强的 NSMapTables,因为弱键的强值不会被清除(和释放),直到/除非映射表调整自身大小。

对不起,我没有更好的解释给你。

于 2017-10-27T20:05:36.930 回答