Objective c与core foundation转换时的内存管理问题
例如NSString与CFStringRef来说
CFStringRef aCFString =(CFStringRef)aNSString;
NSString *aNSString =(NSString *)aCFString;
在ARC下,Objective-C对象系统帮我们做好了相关工作,但是Core Foundation对象的内存管理是需要我们花点儿时间来做好内存管理工作的。这篇文章就讨论一下这个问题。
#ARC下的内存管理
这里我们主要讨论一下Objective-C对象与Core Foundation对象互相转换时候的内存管理问题。 根据需求
1 __bridge_retained 或者 CFBridgingRetain()
__bridge_retained 或者 CFBridgingRetain() 将Objective-C对象转换为Core Foundation对象,把对象所有权桥接给Core Foundation对象,同时剥夺ARC的管理权,后续需要开发者使用CFRelease或者相关方法手动来释放对象。
来看个例子:
NSString *aNSString =[[NSString alloc]initWithFormat:@"test"];
CFStringRef aCFString =(__bridge_retained CFStringRef)aNSString;
//正确的做法应该执行CFRelease
CFRelease(aCFString);
程序没有执行CFRelease,造成内存泄漏.
CFBridgingRetain() 是 __bridge_retained 的宏方法,下面两行代码等价:
CFStringRef aCFString =(__bridge_retained CFStringRef)aNSString;
CFStringRef aCFString =(CFStringRef)CFBridgingRetain(aNSString);
2 __bridge_transfer 或者 CFBridgingRelease()
__bridge_transfer 或者 CFBridgingRelease() 将非Objective-C对象转换为Objective-C对象,同时将对象的管理权交给ARC,开发者无需手动管理内存。
接着上面那个内存泄漏的例子,再转成OC对象交给ARC来管理内存,无需手动管理,也不会出现内存泄漏:
NSString *aNSString =[[NSString alloc]initWithFormat:@"test"];
CFStringRef aCFString =(__bridge_retained CFStringRef)aNSString;
aNSString =(__bridge_transfer NSString *)aCFString;
CFBridgingRelease() 是__bridge_transfer的宏方法,下面两行代码等价:
aNSString =(__bridge_transfer NSString *)aCFString;
aNSString =(NSString *)CFBridgingRelease(aCFString);
3 __bridge
__bridge 只做类型转换,不改变对象所有权,是我们最常用的转换符。
从OC转CF,ARC管理内存:
NSString *aNSString =[[NSString alloc]initWithFormat:@"test"];
CFStringRef aCFString =(__bridge CFStringRef)aNSString;
从CF转OC,需要开发者手动释放,不归ARC管:
CFStringRef aCFString = CFStringCreateWithCString(NULL,"test",kCFStringEncodingASCII);
NSString *aNSString =(__bridge NSString *)aCFString;
CFRelease(aCFString);