Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use CFMutableDictionaryRef with ARC

Is this how you are supposed to use a CFMutableDictionaryRef with ARC?

CFMutableDictionaryRef myDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
NSString *key = @"someKey";
NSNumber *value = [NSNumber numberWithInt: 1];
//ARC doesn't handle retains with CF objects so I have to specify CFBridgingRetain when setting the value
CFDictionarySetValue(myDict, (__bridge void *)key, CFBridgingRetain(value));
id dictValue = (id)CFDictionaryGetValue(myDict, (__bridge void *)key);
//the value is removed but not released in any way so I have to call CFBridgingRelease next
CFDictionaryRemoveValue(myDict, (__bridge void *)key);
CFBridgingRelease(dictValue);//no leak
like image 450
joels Avatar asked Dec 22 '22 01:12

joels


1 Answers

Don't use CFBridgingRetain and CFBridgingRelease here at all. Also, you need to use __bridge when casting the result of CFDictionaryGetValue.

CFMutableDictionaryRef myDict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
NSString *key = @"someKey";
NSNumber *value = [NSNumber numberWithInt: 1];
CFDictionarySetValue(myDict, (__bridge void *)key, (__bridge void *)value);

id dictValue = (__bridge id)CFDictionaryGetValue(myDict, (__bridge void *)key);
CFDictionaryRemoveValue(myDict, (__bridge void *)key);

There is no need for CFBridgingRetain because the dictionary will retain the value anyway. And if you don't call CFBridgingRetain, you don't need to balance it with a release later.

Anyway, this is all much simpler if you just create an NSMutableDictionary and then, if you need a CFMutableDictionary, cast it:

NSMutableDictionary *myDict = [NSMutableDictionary dictionary];
NSString *key = @"someKey";
NSNumber *value = [NSNumber numberWithInt: 1];
[myDict setObject:value forKey:key];

CFMutableDictionaryRef myCFDict = CFBridgingRetain(myDict);
// use myCFDict here
CFRelease(myCFDict);

Note that a CFBridgingRetain can be balanced by a CFRelease; you don't have to use CFBridgingRelease unless you need the id that it returns. Similarly, you can balance a CFRetain with a CFBridgingRelease.

like image 143
rob mayoff Avatar answered Jan 05 '23 19:01

rob mayoff