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
属性,它接受CGColorRef
s 的数组。我的猜测是我应该在这里使用__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>) op
或 CFBridgingRelease(op)
用于消耗 CFTypeRef
的保留计数,同时将其转移到 ARC。这也可以表示为id someObj = (__bridge <NSType>) op; CFRelease(op);
(__bridge_retained <CFType>) op
或CFBridgingRetain(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 和桥接铸件的主要内容,如果未能解决你的问题,请参考以下文章