Crazy Programmer ( 囧rz=З )

文章来源:

在对 bridge 相关的修饰符讲解前,,首先了解以下内容

普通对象与C语言指针之间的转换void *p = NULL;{id obj = [[NSObject alloc] init];p = (__bridge void *)obj;}NSLog(@”Hello”);// 这里会出现错误NSLog(@”%@”, [(__bridge id)p class]);

上面代码中的obj被ARC管理,p是一个C语言指针,不在ARC的管理范围中。当程序执行到obj的作用域之外,ARC便将obj给release掉,这时p指针成为NULL。所以在使用__bridge的时候必须清楚对象的生命周期否则便会出现类似上面的错误。

这时便应该使用__bridge_retain关键字来进行转换

p = (__bridge_retain void *)obj;// 上面这段代码在非ARC的环境下可以表示为p = obj;[(id)p retain];

所以当obj被ARC release后,p指针仍然指向一个有效的对象。

而__bridge_transfer则是用于将一个通过__bridge_retain转换得到的C语言指针重新转换为被ARC管理的普通对象。

id obj = (__bridge_transfer id)p;// 用非ARC来表示就是id obj = p;[obj retain];[(id)p release];

可以看出,__bridge_transfer将p指向的对象的所有权转移到了ARC管理的obj上。

当在ARC环境中声明 id obj 时,默认是 strong 修饰符修饰的,所以ARC会自动对obj进行retain处理,所以说__bridge_transfer只做了release处理。Core Foundation与Foundation普通对象之间的转换

从上面已经知道Core Foundation中的对象也存在引用计数的概念。当在非ARC环境下,Core Foundation对象和Foundation对象可以通过标准的C语言类型转换来进行转换(Toll-Free bridge)。而当引入ARC后则需要bridge来进行转换,因为你需要明确的告诉编译器如何处理对象的所有权。

例如:

NSString *str = [NSString stringWithFormat…];CFStringRef cfStr = (__bridge CFStringRef)str;…CFRelease(cfStr);

这里str对象被ARC所管理,而cfStr并不在ARC的管理中,因为__bridge只是单纯的进行了类型转换,所以当str被ARC release后,cfStr便成为了NULL。

而当上面这段代码使用__bridge_retain进行转换后,cfStr便拥有了str对象的所有权,这时如果str被ARC release,cfStr仍然有效。然而又因为Core Foundation中的对象也存在引用计数概念,所以需要使用CFRelease()手动的对cfStr进行release操作。代码如下:

NSString *str = [NSString stringWithFormat…];CFStringRef cfStr = (__bridge_retain CFStringRef)str;…CFRelease(cfStr);

至于__bridge_transfer,从上文可以得知其用于将对象的所有权转移,所以CF(Core Foundation简写)对象在使用__bridge_transfer转换为Foundation对象后被释放。

CFStringRef cfStr = CFStringCreate…();NSString *str = (__bridge_transfer NSString *)cfStr;// 在非ARC环境下,上面这句等同于NSString *str = cfStr;CFRelease(cfStr);

实际上,在Core Foundation内部存在两个用于CF对象和Foundation对象转换的函数

CFTypeRef CFBridgingRetain(id X) {return (__bridge_retained CFTypeRef)X;}id CFBridgingRelease(CFTypeRef X) {return (__bridge_transfer id)X;}

使用这两个函数同样可以进行两者对象之间的类型转换。

总结

每个人在他的人生发轫之初,总有一段时光,

Crazy Programmer ( 囧rz=З )

相关文章:

你感兴趣的文章:

标签云: