Foundation & Core Foundation类型转换

2017-09-09  本文已影响0人  Nine_suns

简介

Foundation与Core Foundation是两个关联密切的框架,区别主要在于Foundation是以Objective-C实现的,Core Foundation是以C语言实现的。在编程中有时会遇到两个框架内做类型转换,比如NSDictionary与CFDictionary之间的转换。

MRC

在MRC模式下,由于id类型其实也是指向结构体的一个指针,所以可以像C语言一样做类型转换,自己做好内存管理即可。如下:

  NSDictionary *nDict = @{@"key" : @"value"};
  CFDictionaryRef cDict = nDict;
  NSDictionary *nDictOther = cDict;

ARC

在ARC模式下,编译器会为我们做内存管理,但是在遇到这种类型转换的时候,编译器无法判断该怎么处理这种对象的内存管理,即ARC没有办法处理Core Foundation框架下的内存管理问题。所以便有了下面几个关键字:

__bridge
__bridge_retained
__bridge_transfer

上述三个关键字的区别在于对象的内存管理权的处理

名称 描述
__bridge 只做类型转换,内存管理权不变
__bridge_retained 将Foundation对象转换为CoreFoundation对象,交出内存管理权,需要做CFRelease操作,避免内存泄漏
__bridge_transfer 将CoreFoundation对象转为Foundation对象,内存管理权交出,归ARC处理

__bridge

NSDictionary *dict = @{@"key" : @"value"};
CFDictionaryRef cfDict = (__bridge CFDictionaryRef)dict;
dict = nil;
NSLog(@"%@", cfDict);//这时这里会出现EXC_BAD_ACCESS,即访问了野指针。

但是使用NSString时需要注意:

NSString *nsString = @"123";
CFStringRef cfString = (__bridge NSString *)nsString;
nsString = nil;
NSLog(@"%@", cfString);//使用string的这个例子,这么用没有问题

相当于__unsafe_unretained,nsString被设置为nil后,cfString会变成野指针?需确定。
经过确定,只使用__bridge时,的确会在原oc变量释放后cf对象变成野指针的情况,但是不能用NSString这个例子来讲,因为NSString的引用计数受到系统的特殊处理,具体参考链接

__bridge_retained

NSDictionary *nDdict = @{@"key" : @"value"};
CFDictionaryRef cDict = (__bridge_retained CFDictionaryRef)nDict;
nDict = nil;
NSLog(@"%@", cDict);//这时是没问题的
...
CFRelease(cDict);

nDict不再持有内存的管理权,nDict即使设置为nil,也不会影响cDict对内存的引用,需要开发者找个合适的时机去调用CFRelease(cDict)来释放。

__bridge_transfer

CFDictionaryRef cDict = CFDictionaryCreate(CFAllocatorGetDefault(), &("key"), &("value"), 1, NULL, NULL);
NSDictionary *nDict = (__bridge_transfer NSDictionary *)cDict;
//nDict = CFBridgingRelease(cDict);也可以直接用这个函数

cDict对内存的管理权移交给nDict,即ARC来处理。

上一篇 下一篇

猜你喜欢

热点阅读