ARC 和桥接铸件

Posted

技术标签:

【中文标题】ARC 和桥接铸件【英文标题】:ARC and bridged cast 【发布时间】:2011-10-25 13:36:33 【问题描述】:

使用 ARC,我无法再将 CGColorRef 转换为 id。我了解到我需要进行桥接演员表。根据clang docs:

桥接演员表是使用以下三个关键字之一注释的 C 风格演员表:

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

(__bridge_retained T) op 转换操作数,它必须有 可保留对象指针类型,指向目标类型,必须是 不可保留的指针类型。 ARC 保留价值,但须遵守 通常对局部值进行优化,接收者负责 用于平衡 +1。

(__bridge_transfer T) op 转换操作数,它必须有 不可保留的指针类型,指向目标类型,它必须是 可保留对象指针类型。 ARC 会在最后释放值 封闭的完整表达式,服从通常的优化 当地价值观。

需要这些转换才能将对象移入和移出 电弧控制;参见关于转换的部分的基本原理 可保留的对象指针。

使用__bridge_retained__bridge_transfer 演员纯粹是为了说服 ARC分别发出不平衡的保留或释放很差 表格。

我会在什么样的情况下使用它们?

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

【问题讨论】:

你看过 WWDC 2011 session 323 了吗?这比我在这里解释的要好得多。它涵盖了从头到尾的所有细节。这是每个 Mac/ios 开发人员必看的会议。 这可能也有帮助:***.com/questions/14352494/… 链接到 WWDC 会话,找到它并非易事:developer.apple.com/videos/play/wwdc2011/323 – 相关位在 23:15 【参考方案1】:

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

__bridge 在 Objective-C 和 Core Foundation 之间传输一个指针,但没有所有权转移。

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

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

__bridge_transfer (CFBridgingRelease)non-Objective-C 指针移动到 Objective-C,并将所有权转移给 ARC。

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

来源:Toll-Free Bridged Types

【讨论】:

【参考方案2】:

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

(__bridge_transfer <NSType>) opCFBridgingRelease(op) 用于消耗 CFTypeRef 的保留计数,同时将其转移到 ARC。这也可以表示为id someObj = (__bridge <NSType>) op; CFRelease(op);

(__bridge_retained <CFType>) opCFBridgingRetain(op) 用于将NSObject 交给CF-land,同时给它+1 保留计数。您应该像处理CFStringCreateCopy() 的结果一样处理您创建的CFTypeRef。这也可以表示为CFRetain((__bridge CFType)op); CFTypeRef someTypeRef = (__bridge CFType)op;

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

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

【讨论】:

使用 __bridge_transfer 时,对象的保留计数是否会增加 1 弧?否则,似乎在调用 CFRelease() 的那一刻,对象就消失了,并且没有指向任何东西。同样,当您使用 __bridge_retain 时,ARC 是否会将操作的保留计数减少 1?否则,该对象似乎永远不会被正确释放。 在 ARC 领域,您不再考虑保留计数,只考虑强引用和弱引用。 是的,如果你只在 arc 领域 strong/weak 就足够了,但是当你在 arc 和 non-arc 环境之间转换对象时,你仍然必须考虑下的保留计数含义引擎盖 并非如此。您只需要考虑进出 ARC 土地。这与掌握自动释放功能非常相似。 (有趣的是:ARC 修复了一个常见的模式,比如从字典中取出一个对象,然后在使用它之前将其删除,等等。) 使用分析工具(shift + command + B)可以帮助解决此类疑问,因为它会以自然语言告诉您当前代码是否存在内存泄漏。如果是这样,您可能正在使用固定石膏,而您应该使用非固定石膏。如果分析器没有警告您该代码行中的任何内容,则您可能对当前代码做得很好【参考方案3】:

作为后续,在这种特定情况下,如果您使用的是 iOS,Apple 建议使用 UIColor 及其 -CGColor 方法将 CGColorRef 返回到 colors NSArray。在Transitioning to ARC Release Notes中,在“编译器处理从Cocoa方法返回的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) 而不是所有对象。 此问题询问有关使用 ARC 进行投射的问题,您粘贴的代码不合法​​。 @JoeyHagedorn - 也许您在我的回答的第一句话中错过了我对 ARC 文档的引用,但这不仅在 ARC 下有效,而且是从这些向 NSArrays 提供 CGColorRef 引用的推荐方法UIColor 转换器方法。我和其他许多人在启用 ARC 的应用程序中使用这个确切的代码。从返回核心基础对象的方法立即转换为 (id) 会自动将该对象正确地桥接到 ARC。

以上是关于ARC 和桥接铸件的主要内容,如果未能解决你的问题,请参考以下文章

[精通Objective-C]专家级技巧:使用ARC

收集元素的桥梁铸件

__bridge

桥接和NAT的区别

设计模式---桥接模式

虚拟机桥接和NAT用哪个IP不一样?