iOS __bridge 桥接的使用

转自:https://www.jianshu.com/p/bec56131eaeb

30、有时候你可能需要用到一些Core Foundation对象(比如CFArrayRef或者CFMutableDictionaryRef),对于这些对象,编译器是不会自动管理它们的生命周期的,你需要使用CFRetain或CFRelease之类的方法来管理它们的持有情况(ownership)。
如果要进行Core Foundation对象和Objective-C对象的相互转换,就可以使用Toll-Free Bridging。
而由于ARC已不能直接使用retain、release等方法,那么在转换的时候就需要将CF指针的持有情况告知OC指针,同理OC指针在转换成CF指针时也要告知其持有情况。

31、Toll-Free Bridging可以使用修饰符来进行转换,有3种转换方法:
(1)、__bridge
用于两个指针间的直接转换,不考虑持有情况;
(2)、__bridge_retained
用于OC指针转换成CF指针,转换之后CF指针也会持有对象。即是,转换后被赋值的指针也会持有对象。
使用CFBridgingRetain函数也有等同效果;
(3)、__bridge_transfer
用于CF指针(官方文档说的是“非OC指针”)转换成OC指针,转换之后CF指针不再持有对象。即是,转换后赋值指针不再持有对象。
使用CFBridgingRelease函数也有等同效果。

以下用4个例子来演示这3个修饰符:
32、__bridge_retained:
创建一个OC指针,通过__bridge_retained将它转换为CF指针,同时打印出retainCount:

 

 

分析一下这段代码执行过程中的持有情况:

 


可以证明,在使用__bridge_retained修饰符转换后CF指针也会持有对象。

33、__bridge:
如果仅仅使用__bridge做直接转换的话,会有什么问题呢?将32代码中的转换修改为使用__bridge,如下:

 

 

可以发现,在这种情况下会导致悬挂指针。所以仅仅使用__bridge做直接转换的话有时候是很危险的。

34、__bridge_transfer:
创建一个CF指针,通过__bridge_transfer将它转换为OC指针,同时打印出retainCount:

 

 

分析一下这段代码执行过程中的持有情况:

 


可以证明,在使用__bridge_transfer修饰符转换后CF指针不再持有对象。

35、__bridge:
同样的,试一试仅仅使用__bridge来做直接转换,看看会发生什么问题。将34代码中的转换修改为使用__bridge,并嵌套在一层花括号内限制变量的作用域,如下:

 

 

可以发现,在这种情况下会导致内存泄漏。所以在这种情况下仅仅使用__bridge做直接转换也是很危险的。

36、Toll-Free Bridging除了可以做OC指针和CF指针之间的转换,还可以做其他转换,比如上文29(4)提到的id变量和void*变量的相互转换。
虽然在ARC模式下,不允许id变量和void*变量进行直接转换,但是可以使用Toll-Free Bridging来完成这个转换。

37、在研究这种转换之前,先要了解一下void*类型的变量对它指向的对象的持有情况是否会有影响:
(1)、在MRC模式下,由于void*类型并不是NSObject的子类,所以这种类型的变量无法调用retain、retainCount等方法,也即无法影响引用计数。
所以,在MRC模式下void*类型的变量不会对它指向对象的持有情况造成任何影响;
(2)、在ARC模式下,修饰符只能用来修饰OC指针和块指针类型,而void*类型的变量作为一种无类型的变量,修饰符对这种它是不起作用的。
即是说:当定义变量id obj的时候,其实定义的是id __strong obj,而当定义void *obj的时候,定义就仅仅只是void *obj,它的作用类似于使用了__unsafe_unretained修饰符。
所以,在ARC模式下void*类型的变量也不会对它指向的对象的持有情况造成任何影响。

38、前文29(4)的代码在ARC模式下可以使用__bridge来处理如下:

id obj = [[NSObject alloc] init];
void *p = (__bridge void *)obj;
id o = (__bridge id)p;

但是通过上文已知道,仅仅使用__bridge做转换是很危险的,而且void*类型的变量不会持有它指向的对象,这也是很危险的。比如这段代码,总共有3个指针指向了这个NSObject对象,但是它的retainCount却只有2,这样就很容易造成悬挂指针了。

39、如果前两句代码使用__bridge_retained来处理这种转换,代码如下:

id obj = [[NSObject alloc] init];
void *p = (__bridge_retained void *)obj;

由上文已经知道:使用__bridge_retained转换后,被赋值变量也会持有这个对象。所以这段代码其实是相当于在MRC模式下的这样子转换:

id obj = [[NSObject alloc] init];
void *p = obj;
[(id)p retain]; //强转为id类型后才能调用retain

这样void*类型的p变量就拥有了“持有”对象的效果。

40、如果最后一句代码使用__bridge_transfer来处理这种转换,代码如下:

id o = (__bridge_transfer id)p;

由上文已经知道:使用__bridge_transfer转换后,赋值变量不会再持有这个对象。所以这段代码其实是相当于在MRC模式下的这样子转换:

id o = (id)p;
[o retian];
[(id)p release];

这样将p变量赋值给o变量后,p变量便会有“释放”的效果了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1024app_ios_2.3.4是一款专为iOS设备设计的应用程序,其版本号为2.3.4。该应用程序在功能上提供了丰富的内容和服务,可以满足用户在不同方面的需求。 1024app_ios_2.3.4首先具备了强大的应用市场功能,用户可以通过该应用程序方便地浏览和搜索各种类型的应用,包括游戏、社交媒体、工具类等。用户可以根据自己的兴趣和需求下载和安装这些应用,并在手机上进行使用。 其次,1024app_ios_2.3.4还提供了个性化推荐功能,根据用户的使用习惯和喜好,推荐适合用户的应用程序。这样,用户可以更加高效地发现和使用他们感兴趣的应用,提高了用户体验。 另外,1024app_ios_2.3.4还支持应用的更新和升级。用户可以在应用程序中获得关于已安装应用的最新版本信息,并进行更新。这样,用户可以及时获得应用程序的最新功能和修复bug,提高了应用的稳定性和安全性。 最后,1024app_ios_2.3.4还具备了一些额外的功能,例如用户可以在应用中进行应用评分和评论,与其他用户交流和分享使用心得。此外,用户还可以通过该应用程序获取关于应用的详细信息,如应用的大小、开发者介绍等。 综上所述,1024app_ios_2.3.4是一款功能强大的iOS应用程序,用户可以在其中浏览和下载各种类型的应用,享受个性化推荐、应用更新和升级等服务。同时,用户还可以与其他用户互动交流,获取应用的详细信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值