由于ARC不能管理Core Foundation Object的生命周期,所以当我们在Object-C 和 Core Foundation对象之间转换(id 与 void* 之间的转换)时,我们需要使用到__bridge,__bridge_retained和__bridge_transfer三个转换关键字。
_bridge:只做类型转换,但是不修改对象(内存)所有权。例如:
CFMutableArrayRef cfObject = NULL;{id obj = [[NSMutableArray alloc] init]; // obj has a strong reference to the objectcfObject = (__bridge CFMutableArrayRef)obj; // __bridge does not touch ownership status CFShow(cfObject);printf("retain count = %d\n", CFGetRetainCount(cfObject));} CFRelease(cfObject);输出结果是retain count = 1
_bridge_retained(CFBridgingRetain):将Objective-C的对象转换成Core Fundation的对象,同时获得对象所有权,后续使用CFRealease或其他方法释放对象。(_bridge_retained cast works as if the assigned variable has ownership of the object )例如:
/* ARC */id obj = [[NSObject alloc] init];void *p = (__bridge_retained void *)obj;/* non - ARC */id obj = [[NSObject alloc] init]void *p = obj;[(id)p retain];在ARC中,_bridge_retained 代替了retain,上面的obj与p 都拥有对象的所有权。再如:/* ARC */void *p = 0;{ id obj = [[NSObject alloc] init]; p = (_bridge_retained void*)obj;}NSLog(@"class = %@",[(_bridge id)p class]);上面的代码是有输出的。在大括号结束后,obj的所有权是已经释放了,但是p依然拥有对象的所有权,对象不会释放。/* non-ARC */void *p = 0;{ id obj = [[NSObject alloc] init]; //obj 的retainCount 为1 p = [obj retain]; // obj 的retainCount 为2 [obj release]; // obj 的retainCount 为1 /*[(id)p retainCount] 为1,所有对象是依然存在的 */}NSLog(@"class = %@",[(_bridge id)p class]);
CFBridgingRetain:
CFBridgingRetain的实现方法:CFTypeRef CFBridgingRetain(id X) {return (__bridge_retained CFTypeRef)X;}例子: CFMutableArrayRef cfObject = NULL; {id obj = [[NSMutableArray alloc] init]; // obj has a strong reference to the objectcfObject = CFBridgingRetain(obj); // the object is assigned to cfObjectCFShow(cfObject); printf("retain count = %d\n", CFGetRetainCount(cfObject)); }printf("retain count after the scope = %d\n", CFGetRetainCount(cfObject));CFRelease(cfObject); // the object is discarded输出结果是:retain count = 2;//One is for strong reference of variable obj,the other is by CFBridgingRetainretain count after the scope = 1;//leaving the scope strong reference disappears
_bridge_transfer(CFBridgingRelease):当想把本来拥有对象所有权的变量,在类型转换后,让其释放原先所有权的时候(__bridge_transfer cast will release the object just after the assignment is done )
/* ARC */id obj = (__bridge_transfer id)p; /* non-ARC */id obj = (id)p;[obj retain];[(id)p release];
CFBridgingRelease:
CFBridgingRelease的实现方法: id CFBridgingRelease(CFTypeRef X) { return (__bridge_transfer id)X;} 例子:{CFMutableArrayRef cfObject = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL);printf("retain count = %d\n", CFGetRetainCount(cfObject));id obj = CFBridgingRelease(cfObject);printf("retain count after the cast = %d\n", CFGetRetainCount(cfObject));NSLog(@"class=%@", obj);}