Создание пользовательских обратных вызовов CFDictionary - PullRequest
3 голосов
/ 29 января 2011

Я пытаюсь реализовать категории для класса 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. Вопрос в том, являются ли эти допустимые обратные вызовы для этого случая? Что-то не так в моем коде, кроме этого?

Ответы [ 2 ]

2 голосов
/ 13 июня 2012

Мне пришлось написать их самостоятельно, как только я не нашел стандартных базовых обратных вызовов для сохранения и освобождения ключей.

Я думаю, что вы после CFRetain и CFRelease. Но если вы хотите изменить только обратные вызовы клавиш, вы можете использовать стандарт kCFTypeDictionaryValueCallBacks.

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

    return [(id)CFDictionaryCreateMutable(NULL, capacity, &keyCallbacks, &kCFTypeDictionaryValueCallBacks) autorelease]; 
}
2 голосов
/ 30 января 2011

Я не вижу ничего плохого в этих обратных вызовах, как таковых. Тем не менее, вы должны быть осторожны с «раздачей» NSMutableDictionaries «публике», которая не ведет себя как обычные NSMutableDictionaries.

Чтобы уточнить, предоставление кому-либо указателя NSMutableDictionary неявно делает заявления о том, как ведет себя этот объект. Установив его как CFMutableDictionary с нестандартными обратными вызовами, и применив его с помощью магии компиляции Toll-Free Bridging, но настраивая потребителя на отказ.

В более общем смысле, я бы сказал, что вы можете делать это безнаказанно, если вы сохраняете словарь закрытым для любого класса, которым он принадлежит. Ваш фрагмент кода подразумевает, что вы можете передать это «остальному миру» под видом NSMutableDictionary, хотя это не совсем так.

Если вам нужно передать эти экземпляры, я бы порекомендовал создать свой собственный подкласс NSMutableDictionary, такой как «MyWeakRefKeyMutableDictionary», и явно возвращать этот тип. Тогда, по крайней мере, если кто-то рассматривает его как NSMutableDictionary, он не может сказать, что его не предупредили.

...