ChatGPT解决这个技术问题 Extra ChatGPT

使用 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 将在封闭的完整表达式的末尾释放该值,这取决于对局部值的通常优化。需要这些转换才能将对象移入和移出 ARC 控制;请参阅关于可保留对象指针的转换部分的基本原理。纯粹使用 __bridge_retained 或 __bridge_transfer 强制转换来说服 ARC 分别发出不平衡的保留或释放是不好的形式。

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

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

你看过 WWDC 2011 session 323 了吗?这比我在这里解释的要好得多。它涵盖了从头到尾的所有细节。这是每个 Mac/iOS 开发人员必看的课程。
链接到 WWDC 会议,找到它并非易事:developer.apple.com/videos/play/wwdc2011/323 – 相关位在 23:15

B
Ben Mosher

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

(__bridge_transfer ) op 或 CFBridgingRelease(op) 用于消耗 CFTypeRef 的保留计数,同时将其传输到 ARC。这也可以用 id someObj = (__bridge ) op; 来表示。 CFR 释放(操作);

(__bridge_retained ) 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 土地。这与掌握自动释放功能非常相似。 (有趣的是:ARC 修复了一个常见的模式,比如从字典中取出一个对象,然后在使用它之前将其删除,等等。)
使用分析器工具(shift + command + B)可以帮助解决此类疑问,因为它会以自然语言告诉您当前代码是否泄漏内存。如果是这样,您可能正在使用固定石膏,而您应该使用非固定石膏。如果分析器没有警告您该代码行中的任何内容,则您可能对当前代码做得很好
h
hashier

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

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

__bridge_retained (CFBridgingRetain) 将 Objective-C 指针转换为 Core Foundation 指针,并将所有权转移给您。您负责调用 CFRelease 或相关函数来放弃对象的所有权。

__bridge_transfer (CFBridgingRelease) 将非 Objective-C 指针移动到 Objective-C 并将所有权转移给 ARC。 ARC 负责放弃对象的所有权。

来源:Toll-Free Bridged Types


B
Brad Larson

作为后续,在这种特定情况下,如果您使用的是 iOS,Apple 建议使用 UIColor 及其 -CGColor 方法将 CGColorRef 返回到 colors NSArray。在 Transitioning to ARC Release Notes 中,在“编译器处理从 Cocoa 方法返回的 CF 对象”部分下,指出使用像 -CGColor 这样返回核心基础对象的方法将由编译器自动正确处理。

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

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 下有效,而且是从这些 UIColor 转换器方法向 NSArrays 提供 CGColorRef 引用的推荐方法。我和其他许多人在启用 ARC 的应用程序中使用这个确切的代码。从返回核心基础对象的方法立即转换为 (id) 会自动将该对象正确地桥接到 ARC。