3

我正在尝试使用至少两种方法为 NSMutableDictionary 类实现类别:一种用于保留(不复制)其键的 NSDictionary,另一种用于弱引用其键(即对它们不做任何事情)的 NSDictionary。

在这两种情况下,值都被简单地保留。

因此,据说 CFDictionaryRef 与 NSDictionary 是免费桥接的,我实际上做了以下事情:

+ (NSMutableDictionary *)dictionaryWithWeakReferencedKeysForCapacity: (NSUInteger)capacity
{   
    CFDictionaryKeyCallBacks    keyCallbacks    = { 0, NULL, NULL, CFCopyDescription, CFEqual, NULL }; 
    CFDictionaryValueCallBacks  valueCallbacks  = { 0, ___f_KBWS_DICTIONARY_RETAIN_CALLBACK, ___f_KBWS_DICTIONARY_RELEASE_CALLBACK, CFCopyDescription, CFEqual };

    return [(id)CFDictionaryCreateMutable(NULL, capacity, &keyCallbacks, &valueCallbacks) autorelease]; 
}

第二种方法(用于保留键)看起来很相似,此处不再介绍。代码中的可怕功能是:

static const void *___f_KBWS_DICTIONARY_RETAIN_CALLBACK(CFAllocatorRef allocator, const void *value)
{
    id object = (id)value;
    return [object retain];
};

static void ___f_KBWS_DICTIONARY_RELEASE_CALLBACK(CFAllocatorRef allocator, const void *value)
{
    id object = (id)value;
    return [object release];
};

一旦我没有找到用于保留和释放密钥的标准核心基础回调,我就不得不自己编写这些。

我计划将这些类别用于仅存储子类 NSObjects 的字典。问题是:对于这种情况,这些有效的回调吗?除此之外,我的代码还有什么问题吗?

4

2 回答 2

2

我认为这些回调本身没有任何问题。也就是说,你应该小心将 NSMutableDictionaries “分发”给与普通 NSMutableDictionaries 不同的“公众”。

详细地说,给某人一个 NSMutableDictionary 指针隐含地说明了该对象的行为方式。已将其设置为 CFMutableDictionary,具有非标准回调,并通过免费桥接编译的魔力进行转换,但正在为消费者设置失败。

更一般地说,我会说,只要您将字典对拥有它的任何班级保密,您就可以不受惩罚地做到这一点。您的代码片段暗示您可能会以 NSMutableDictionary 的名义将其分发给“世界其他地方”,而事实并非如此。

如果您必须分发这些实例,我建议您制作自己的自定义 NSMutableDictionary 子类,例如“MyWeakRefKeyMutableDictionary”并显式返回该类型。那么至少如果有人把它当作一个 NSMutableDictionary,他们不能说他们没有被警告过。

于 2011-01-30T03:41:53.003 回答
2

一旦我没有找到用于保留和释放密钥的标准核心基础回调,我就不得不自己编写这些。

我想你在追求CFRetainand CFRelease。但如果您只想更改键回调,您可以使用标准的kCFTypeDictionaryValueCallBacks.

+ (NSMutableDictionary *)dictionaryWithWeakReferencedKeysForCapacity: (NSUInteger)capacity
{   
    CFDictionaryKeyCallBacks    keyCallbacks    = { 0, NULL, NULL, CFCopyDescription, CFEqual, NULL }; 

    return [(id)CFDictionaryCreateMutable(NULL, capacity, &keyCallbacks, &kCFTypeDictionaryValueCallBacks) autorelease]; 
}
于 2012-06-13T09:32:16.250 回答