44

__bridge __bridgeretained __bridgetransfer的区别

 4 years ago
source link: https://www.tuicool.com/articles/MNNbiqj
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

iOS开发中,经常会接触到两种对象,Objective-C对象和Core Foundation对象,他们之间有所不同,可以互相转换。最大的不同之处在于,在ARC模式下,前者不用开发者手动管理内存,后者需要开发者手动管理内存,即调用CFRelease方法释放对象,否则会造成内存泄漏。转换的话主要会用到以下3个方法:

  • __bridge,
  • __bridge_retained
  • __bridge_transfer

__bridge可以用于OC对象和CF对象互转,例如

NSObject *obj = [[NSObject alloc] init];    //retain count 1
CFTypeRef cfObj1 = (__bridge CFTypeRef)obj; //retain count 1
NSObject *obj1 = (__bridge id)cfObj1;       //retain count 2

在这种转换方式下,如果是OC对象转换成CF对象,引用计数不变,如果是CF对象转换成OC对象,引用计数会+1。

__bridge_retained用于OC对象转换为CF对象,例如

NSObject *obj = [[NSObject alloc] init];                //retain count 1
CFTypeRef cfObj1 = (__bridge_retained CFTypeRef)obj;    //retain count 2

//等价写法
NSObject *obj = [[NSObject alloc] init];                //retain count 1
CFTypeRef cfObj1 = (CFTypeRef)CFBridgingRetain(obj);    //retain count 2

这种情况下,obj的引用计数会+1,obj的释放不会影响到cfObj1的使用

__bridge_transfer用于CF对象转换为OC对象,例如

NSObject *obj = [[NSObject alloc] init];                //retain count 1
CFTypeRef cfObj1 = (__bridge_retained CFTypeRef)obj;    //retain count 2
NSObject *obj1 = (__bridge_transfer id)cfObj1;          //retain count 2

//等价写法
NSObject *obj = [[NSObject alloc] init];                  //retain count 1
CFTypeRef cfObj1 = (__bridge_retained CFTypeRef)obj;      //retain count 2
NSObject *obj1 = (NSObject *)CFBridgingRelease(cfObj1);   //retain count 2

最后来做个练习,看下以下代码输出什么

NSObject *obj = [[NSObject alloc] init];                //retain count 1
CFTypeRef cfObj = (__bridge_retained CFTypeRef)obj;     //retain count 2
CFTypeRef cfObj1 = (__bridge CFTypeRef)obj;             //retain count 2
CFTypeRef cfObj2 = (__bridge_retained CFTypeRef)obj;    //retain count 3

NSObject *obj1 = (__bridge_transfer id)cfObj1;          //retain count 3
NSObject *obj2 = (__bridge id)cfObj2;                   //retain count 4

NSLog(@"obj retainCount %ld", (long)CFGetRetainCount(cfObj));

NSString *str = [NSString stringWithFormat:@"testStr"];
CFStringRef cfStr = (__bridge CFStringRef)str;
NSLog(@"str retainCount %ld", (long)CFGetRetainCount(cfStr));   //retain count 9223372036854775807 = 0x7FFFFFFFFFFFFFFF

答案是

obj retainCount 4
str retainCount 9223372036854775807

str会被当做是字符串常量,retainCount是一个最大值,保证不会被系统回收。

个人认为苹果的这套API设计得不是很好,比如__bridge,并不是说引用计数不增加,而是看是转换的关系是什么,需要理解记忆一下才行。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK