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。)