Core Foundation 对象内存管理

2,566 阅读2分钟

ARC 对于Core Foundation对象的内存管理是无效,需要手动添加CFRelease、CFRetain消息

    // 创建 CFStringRef 对象
    CFStringRef strRef = CFStringCreateWithCString(kCFAllocatorDefault, "hello world", kCFStringEncodingUTF8);
    // 创建
    CTFontRef fontRef = CTFontCreateWithName((CFStringRef)@"ArialMT", 12, NULL);
    
    // 引用计数加一
    CFRetain(strRef);
    CFRetain(fontRef);
    
    // 引用计数减一
    CFRelease(strRef);
    CFRelease(fontRef);

对于CFRelease、CFRetain可以直观认为与Object-C中的retain、release等价。因此对于底层Core Foundation对象,依然需要手动引用计数来管理内存。

Core Foundation对象与Object-C对象的转化

  • __bridge: 制作类型转化,不操作对象的引用计数,原来的CF对象不需要时,需要动手调用CFRelease方法;
NSString *string = [NSString stringWithFormat:...];
CFStringRef cfString = (__bridge CFStringRef)string;

只是单纯地执行了类型转换,没有进行所有权的转移,也就是说,当string对象被释放的时候,cfString也不能被使用了

  • __bridge_retain: 类型转换后,将相关对象的引用计数加1,原来的CF对象不需要时,需要动手调用CFRelease方法;
NSString *string = [NSString stringWithFormat:...];
CFStringRef cfString = (__bridge_retained CFStringRef)string;
...
CFRelease(cfString); // 由于Core Foundation的对象不属于ARC的管理范畴,所以需要自己release

使用 __bridge_retained 可以通过转换目标处(cfString)的 retain 处理,来使所有权转移。即使 string 变量被释放,cfString 还是可以使用具体的对象。只是有一点,由于Core Foundation的对象不属于ARC的管理范畴,所以需要自己release。

  • __bridge_transfre: 类型转换后,将对象的引用计数交给ARC管理,CF对象不需要时,不需要调用CFRelease方法;
CFStringRef cfString = CFStringCreate...();
NSString *string = (__bridge_transfer NSString *)cfString;
// CFRelease(cfString); 因为已经用 __bridge_transfer 转移了对象的所有权,所以不需要调用 release

所有权被转移的同时,被转换变量将失去对象的所有权。当Core Foundation对象类型向Objective-C对象类型转换的时候,会经常用到 __bridge_transfer 关键字