ARC和桥接铸造


166

使用ARC,我无法再转换CGColorRefid。我了解到我需要进行桥接。根据c文件

桥连投是C样式转换标注有三个关键字之一:

(__bridge T) op将操作数强制转换为目标类型T。如果T 是可保留对象指针类型,则op必须具有不可保留指针类型。如果T是不可保留的指针类型,则op必须具有可保留的对象指针类型。否则,演员表的格式不正确。没有所有权转移,并且ARC不插入保留操作。

(__bridge_retained T) op将必须具有可保留对象指针类型的操作数强制转换为必须是不可保留指针类型的目标类型。ARC保留该值,但要对本地值进行通常的优化,并且接收方负责平衡+1。

(__bridge_transfer T) op将必须具有不可保留的指针类型的操作数强制转换为必须是可保留的对象指针类型的目标类型。ARC将在封闭的全表达式结束时释放该值,但要对本地值进行通常的优化。

这些转换是必需的,以便在ARC控制中进出对象。请参阅有关可保留对象指针的转换部分的基本原理。

仅使用a __bridge_retained__bridge_transfercast来说服ARC分别发出不平衡的保留或释放是不好的形式。

我会在哪种情况下使用它们?

例如,CAGradientLayer具有一个colors接受CGColorRefs 数组的属性。我的猜测是我应该__brige在这里使用,但是不清楚为什么应该(或者不应该)。


17
您是否看过WWDC 2011会议323?这说明ARC比我在这里能做的更好。它涵盖了从头到尾的所有细节。每个Mac / iOS开发者都必须参加该会议。
rbrown


链接到WWDC会话,发现它并非易事:developer.apple.com/videos/play/wwdc2011/323 –相关位在23:15
Daniel

Answers:


215

我同意该描述令人困惑。由于我刚刚掌握了它们,因此我将尝试总结一下:

  • (__bridge_transfer <NSType>) op或者CFBridgingRelease(op)用于CFTypeRef在将其转移到ARC时消耗一次保留计数。这也可以用id someObj = (__bridge <NSType>) op; CFRelease(op);

  • (__bridge_retained <CFType>) op或者可CFBridgingRetain(op)用于NSObject在将其保留为+1的同时移交给CF土地。您应该CFTypeRef以与处理的结果相同的方式处理以这种方式创建的a CFStringCreateCopy()。这也可以用CFRetain((__bridge CFType)op); CFTypeRef someTypeRef = (__bridge CFType)op;

  • __bridge只是在指针和Objective-C对象之间转换。如果您不愿意使用上述转换,请使用此转换。

也许这是有帮助的。就我自己而言,我更喜欢CFBridging…宏而不是普通演员。


当您使用__bridge_transfer时,对象保留计数是否会按弧度增加1?否则,似乎在调用CFRelease()的那一刻该对象消失了,并且没有指向任何对象。同样,当您使用__bridge_retain时,ARC是否会将操作的保留计数减少1?否则,似乎该对象将永远无法正确释放。
托尼

2
一旦进入ARC领域,您就不再考虑保留计数,而只考虑强引用和弱引用。
monkeydom 2012年

4
是的,如果您仅在弧形土地上强/弱就足够了,但是,当您在弧形和非弧形环境之间转换对象时,您仍然必须考虑引擎盖下的保留计数的含义
Tony

3
并不是的。您只需要考虑进出ARC土地。这对于掌握自动释放功能非常有帮助。(足够有趣的是:ARC修复了一种常见的模式,例如从字典中取出一个对象,然后在使用它之前将其删除,等等。)
monkeydom 2012年

3
使用分析器工具(Shift + Command + B)可以帮助解决此类疑问,因为如果当前代码正在泄漏内存,它将以自然语言告诉您。如果是这样,则可能是在使用固定型铸件,而应该使用非固定型铸件。如果分析器未在该代码行中警告您任何问题,则可能是当前代码效果很好
Fabio Napodano

55

我在iOS文档中找到了另一个我认为更容易理解的解释:

  • __bridge 在Objective-C和Core Foundation之间转移指针,而没有所有权转移。

  • __bridge_retained (CFBridgingRetain)Objective-C指针转换为Core Foundation指针,还将所有权转让给您。

    您负责调用CFRelease或相关函数来放弃该对象的所有权。

  • __bridge_transfer (CFBridgingRelease)非Objective-C指针移动到Objective-C,还将所有权转移到ARC。

    ARC负责放弃对象的所有权。

资料来源:免费电话桥接类型


33

作为后续操作,在这种特定情况下,如果您使用的是iOS,Apple建议使用UIColor及其-CGColor方法将CGColorRef返回到colorsNSArray。在过渡到ARC发行说明中的“编译器处理从可可方法返回的CF对象”部分下,指示使用类似-CGColor返回Core Foundation对象的方法将由编译器自动正确处理。

因此,他们建议使用如下代码:

CAGradientLayer *gradientLayer = (CAGradientLayer *)[self layer];
gradientLayer.colors = [NSArray arrayWithObjects:(id)[[UIColor darkGrayColor] CGColor],
                                                 (id)[[UIColor lightGrayColor] CGColor], nil];

请注意,到目前为止,Apple的示例代码缺少我上面的(id)强制转换,这对于避免编译器错误仍然是必需的。


如果愿意,通常可以只将第一个对象投射到(id)而不是全部对象。
Philippe Sabourin

1
这个问题询问有关使用ARC进行转换的问题,您粘贴的代码是不合法的。
乔伊·哈格拉多恩

11
@JoeyHagedorn-也许您在答案的第一句话中错过了我对ARC文档的引用,但这不仅在ARC下有效,而且是从这些UIColor转换器方法向NSArrays提供CGColorRef引用的推荐方法。我和其他许多人在启用ARC的应用程序中使用此确切的代码。从返回Core Foundation对象的方法直接转换为(id)会自动将该对象正确桥接到ARC。
布拉德·拉尔森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.