我正在使用一个供应商API,它返回一个CFDictionaryRef,它可以包含各种CF对象类型,调用者需要CFRelease。我想将它转换为NSDictionary以便更容易地使用它,并且希望确保我理解我正在按照强制转换处理元素。
在我看来,像免费的桥接类型(例如CFString,CFNumber)只是由NSDictionary处理,我可以像我一样,如果他们一直是Obj-C类型那样得到NS类型(我是猜测封面下有一座桥梁。)
对于非免费桥接类型(例如CFHost),看起来我可以将-valueForKey:的结果转换为CF类型并从那里开始,但是如果我需要释放那个,我不是肯定的价值与否。
以下是一些说明问题的示例代码。这是处理事情的正确方法吗?
// Caller is responsible for releasing returned value
//
+ (CFDictionaryRef)someCFCreateFunctionFromVendor
{
CFMutableDictionaryRef cfdict = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(cfdict, CFSTR("string1"), CFSTR("value"));
int i = 42;
CFDictionarySetValue(cfdict, CFSTR("int1"), CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &i));
CFHostRef host = CFHostCreateWithName(kCFAllocatorDefault, CFSTR("myhost"));
CFDictionarySetValue(cfdict, CFSTR("host1"), host);
return cfdict;
}
+ (void)myMethod
{
NSDictionary *dict = CFBridgingRelease([self someCFCreateFunctionFromVendor]);
for (NSString *key in [dict allKeys]) {
id value = [dict valueForKey:key];
NSLog(@"%@ class: %@", key, [value class]);
if ([value isKindOfClass:[NSString class]]) {
NSString *str = (NSString *)value;
NSLog(@"%@ is an NSString with value %@", key, str);
} else if ([value isKindOfClass:[NSNumber class]]) {
NSNumber *num = (NSNumber *)value;
NSLog(@"%@ is an NSNumber with value %@", key, num);
} else if ([value isKindOfClass:[NSHost class]]) {
NSLog(@"%@ is an NSHost", key); // never hit because no toll-free bridge to NSHost
} else {
NSLog(@"%@ is an unexpected class", key);
}
// Sample handling of non-toll-free bridged type
if ([key isEqualToString:@"host1"]) {
CFHostRef host = (__bridge CFHostRef)value;
NSArray *names = (__bridge NSArray *)(CFHostGetNames(host, false));
NSLog(@"host1 names: %@", names);
// I don't think I need to CFRelease(host) because ARC is still handling value
}
}
}
...输出
string1 class: __NSCFConstantString
string1 is an NSString with value strvalue
int1 class: __NSCFNumber
int1 is an NSNumber with value 42
host1 class: __NSCFType
host1 is an unexpected class
host1 names: ( myhost )
答案 0 :(得分:0)
具有讽刺意味的是,您的代码中唯一的错误是在Core Foundation中,非ARC内容。您的+someCFCreateFunctionFromVendor
方法调用CFNumberCreate()
和CFHostCreateWithName()
,两者都是创建函数,但在将对象添加到字典后不会CFRelease()
。这应该。否则,这是泄漏。顺便说一下,静态分析仪会抓住它。 (对于CFNumber
,这意味着您必须将创建拆分为单独的行,以便在将对象添加到字典后引用该对象。)
您不得在+myMethod
中释放主机对象,因为该代码不会获得它的所有权。它与ARC无关。你不会在MRR(手动保留/释放)代码中发布它。