tl;博士:
CFDictionaryRef
使用提供的默认回调函数创建一个。它会做你想做的事。只是不要称它为NSDictionary
.
是的,您可以创建一个CFDictionaryRef
保留其密钥且不复制它们的密钥。事实上,这是a的默认行为CFDictionaryRef
。
的文档CFDictionaryCreateMutable()
说:
如果字典将仅包含 CFType 对象,则传递一个指向kCFTypeDictionaryKeyCallBacks
作为此参数的指针以使用默认回调函数。
(因此,如果您只想将普通的 Objective-C 对象放入数组中,而不是像void *
指针或其他任何随机的东西,这就是您想要的)
并且文档kCFTypeDictionaryKeyCallBacks
说:
CFDictionaryKeyCallBacks
包含一组回调的预定义结构,适用于当 CFDictionary 的键都是 CFType 派生对象时使用。保留回调是CFRetain
,释放回调是CFRelease
,复制回调是CFCopyDescription
,相等回调是CFEqual
。因此,如果您在创建字典时使用指向该常量的指针,则键在添加到集合时会自动保留,并在从集合中移除时释放。
请注意,retain
回调是CFRetain()
而不是类似的东西CFCopyObject
(实际上并不存在)。
事实上,Core Foundation 没有“复制任何对象”的规范方法,这就是存在 , , 等函数CFStringCreateCopy
的CFArrayCreateCopy
原因CGPathCreateCopy
。
所以,你可以做的是像这样创建你的字典:
CFDictionaryRef dict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
你现在有一个字典,它保留了它的键并且不复制它们。
我将用大写字母写下以下内容,以便您了解我要说的内容:
您创建的这本字典不是NSDictionary
.
是的,NSDictionary
并且CFDictionaryRef
是免费桥接的。但是将其转换CFDictionaryRef
为 anNSDictionary
将滥用该桥接,因为NSDictionary
文档中的这一行:
...一个键可以是任何对象(只要它符合NSCopying
协议——见下文)
同样,文档-[NSMutableDictionary setObject:forKey:]
明确说:
复制密钥(使用copyWithZone:
; 密钥必须符合 NSCopying 协议)。
字典中的键不必符合<NSCopying>
并且不使用复制-copyWithZone:
,这意味着您的字典不是NSDictionary
(或NSMutableDictionary
)。每当您NSDictionary
在代码中看到使用时,您都应该提供一个键值映射,其中键被复制(不保留)。那就是 API 合约。做任何其他事情都可能导致未定义的行为。
-copy
(某些对象覆盖的事实return [self retain]
是一个实现细节,与“什么是”的讨论无关NSDictionary
。)