我正在试图弄清楚如何创建一个保留而不是复制其键的NSMutableDictionary。我已经实现了 - (NSUInteger)哈希和 - (id)isEqual:对于我想要的密钥,我只是弄清楚要在回调中指定哪些选项。
CFDictionaryKeyCallBacks keyCallbacks = { 0, NULL, NULL, CFCopyDescription, CFEqual, NULL };
self.commonParents = (NSMutableDictionary*)CFBridgingRelease(CFDictionaryCreateMutable(nil, 0, &keyCallbacks, &kCFTypeDictionaryValueCallBacks));
上面的代码在ARC中正确使用对键的弱引用,但是如果我想要强引用呢?关键回调应该是什么样的?
答案 0 :(得分:5)
TL; DR:
使用提供的默认回调函数创建CFDictionaryRef
。它会做你想要的。不要将其称为NSDictionary
。
是的,您可以创建一个CFDictionaryRef
来保留其密钥而不会复制它们。事实上,这是CFDictionaryRef
的默认行为。
CFDictionaryCreateMutable()
的文档说:
如果字典只包含CFType对象,则将指针作为此参数传递给
kCFTypeDictionaryKeyCallBacks
,以使用默认的回调函数。
(所以,如果您只是将普通的Objective-C对象放入数组而不是随机的东西,如void *
指针或其他什么,这就是你想要的)
kCFTypeDictionaryKeyCallBacks
的文档说:
预定义
CFDictionaryKeyCallBacks
结构,包含一组适用于CFDictionary的键都是CFType派生对象时使用的回调。 保留回调为CFRetain
,发布回调为CFRelease
,副本回调为CFCopyDescription
,相等的回调为CFEqual
。因此,如果在创建字典时使用指向此常量的指针,则在添加到集合时会自动保留键,并在从集合中删除时释放。
请注意,retain
回调为CFRetain()
,而不是CFCopyObject
(实际上并不存在)。
事实上,Core Foundation并没有采用规范的方式来复制任何对象",这就是CFStringCreateCopy
,CFArrayCreateCopy
,{{1}等功能的原因等存在。
所以,你能做的就是像这样创建你的字典:
CGPathCreateCopy
现在你有一个字典可以保留其密钥并且不会复制它们。
我要用大字写下这一点,这样你就可以说出我要说的话了:
CFDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
。是的,NSDictionary
和NSDictionary
是免费桥接的。但是将这个CFDictionaryRef
强制转换为CFDictionaryRef
会滥用这种过渡,因为NSDictionary
文档中的这一行:
......密钥可以是任何对象(前提是它符合
NSDictionary
协议 - 见下文)
同样,NSCopying
的文档明确说明:
密钥被复制(使用
-[NSMutableDictionary setObject:forKey:]
;密钥必须符合NSCopying协议。)
词典中的键不必符合copyWithZone:
,也不会使用<NSCopying>
复制,这意味着您的词典不是-copyWithZone:
(或{{1 }})。每当您在代码中看到NSDictionary
时,您应该提供键值复制(未保留)的键值映射。这是API合同。做任何其他事情都可能导致未定义的行为。
(某些对象覆盖NSMutableDictionary
到NSDictionary
这一事实是一个实现细节,与此讨论无关,&#34;什么是-copy
&#34;。 )
答案 1 :(得分:1)
我认为最好的答案隐藏在评论中,所以我在这里强调一下:最简单的方法是使用+[NSMapTable strongToStrongObjectsMapTable]
(或者可能是带有weak
引用的变体之一)。< / p>
答案 2 :(得分:0)
我建议你不要这样做,而是将NSString或你正在使用的任何类作为键的子类,并以一种方式覆盖复制方法,使其返回保留的字符串,而不是复制的字符串。
答案 3 :(得分:0)
我认为使用普通的NSMutableDictionary可以实现两种可能的解决方案。它们并不像NSMapTable那样优雅。
您声明每个密钥都有uniqueID
,因此我假设此值不会随时间而变化。
选项1 :
使用实际密钥的uniqueID
作为NSMutableDictionary的密钥,它将存储@[key, value]
的NSArray,因此整个结构看起来像这样
@{ key1.uniqueID : @[key1, value1], key2.uniqueID : @[key2 : value2] }
选项2 :
创建NSObject的子类,它是选项1的包装。或选项1的任何变体。
仅在uniqueID
永不改变