【发布时间】:2011-01-29 20:51:41
【问题描述】:
我正在尝试使用至少两种方法为 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 的字典。 问题是:对于这种情况,这些有效的回调吗? 除此之外,我的代码还有什么问题吗?
【问题讨论】:
-
有点 OT:您通常应该为其他开发人员(例如苹果)提供的 NSObject 子类的类别方法添加前缀。例如:
+ (NSMutableDictionary *)kbws_dictionaryWithWeakReferencedKeysForCapacity: (NSUInteger)capacity。此外,您通常还希望提供哈希回调。散列码对于 cfdictionaries 非常重要 - 在大多数情况下这将是最好的,因为它给出了典型的(预期的)结果。如果您不提供哈希回调,则哈希码基于地址(在某些情况下这是有效行为)。 -
感谢贾斯汀对这个话题的评论;哈希码,是的,我被警告过,稍后会处理它们:) 你能解释一下为方法名称添加前缀的原因吗?
-
是的。这与为类名添加前缀的原因相同。 objc 为类和方法使用平面命名空间。也无法通过语法指定类别方法。因此,如果您加载到应用程序中的任何二进制文件使用相同的类或方法名称,那么其中一个实现将被忽略,并且有人不会从消息传递中获得他们期望的结果/效果/实现。前缀减少了这种可能性。哪个方法被忽略是未定义的(afaik),但您可能最终会得到加载到进程中的第一个实现。
-
(cont) 因此任何加载的库/插件或合成接口都可以将此方法添加到 objc 运行时,这将导致冲突并将 UB 传递给调用者。
标签: iphone objective-c callback nsdictionary core-foundation