首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >NSMapTable是如何工作的

NSMapTable是如何工作的
EN

Stack Overflow用户
提问于 2017-10-27 19:34:49
回答 3查看 3.6K关注 0票数 6

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

代码语言:javascript
运行
复制
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中有一个元素?

EN

回答 3

Stack Overflow用户

发布于 2017-10-30 20:09:46

当您不关心何时释放键/值时,NSMapTableweak行为选项工作得最好,但是您确实关心的是,键/值没有被强烈保留,并且在感兴趣的对象成为nil之后会在某个时候释放。

为什么会这样呢?

作为一个基础类,NSMapTable的作者必须平衡特性和性能。

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

正如@路克在他的回答中所提到的,更多细节请看这篇关于NSMapTable行为实验的优秀文章:

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

票数 7
EN

Stack Overflow用户

发布于 2017-10-27 20:05:36

是的,这是一种奇怪而不幸的行为。这篇文章深入研究了它。虽然它没有具体地探讨弱到弱,但描述的行为是一样的。正如作者所指出的,hobyePerson.keyEnumerator().allObjects.counthobyePerson.objectEnumerator().allObjects.count将包含0,这一切结束时都是预期的。他还指出,苹果在山狮发行说明中记录了这种行为。

但是,弱到强的NSMapTables目前不被推荐,因为弱键的强值得到零d输出,直到/除非映射表自身调整大小,否则不会被清除(并释放)。

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

票数 2
EN

Stack Overflow用户

发布于 2022-06-29 19:13:49

它对我不起作用,所以我实现了这样简单的弱映射。会改善它的加班,但现在起作用了:

代码语言:javascript
运行
复制
import Foundation

private struct WeakValue<Value:AnyObject> {
    weak var value: Value?
}

public class CSWeakValueDictionary<Key:AnyObject, Value:AnyObject> {
    private let dictionary = NSMutableDictionary()
    public subscript(source: Key) -> Value? {
        get {
            let value = (dictionary["\(source)"] as? WeakValue<Value>)?.value
            if value == nil { dictionary.removeObject(forKey: "\(source)") }
            return value
        }
        set { dictionary["\(source)"] = WeakValue(value: newValue) }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46982265

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档