使用 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
,但我究竟为什么应该(或不应该)尚不清楚。
我同意描述令人困惑。由于我刚刚掌握了它们,因此我将尝试总结一下:
(__bridge_transfer
(__bridge_retained
__bridge 只是在指针域和 Objective-C 对象域之间进行转换。如果您不想使用上述转换,请使用此转换。
也许这很有帮助。我自己,我更喜欢 CFBridging…
宏而不是普通的演员。
我在 iOS 文档中找到了另一种我认为更容易理解的解释:
__bridge 在 Objective-C 和 Core Foundation 之间传输一个指针,但没有所有权转移。
__bridge_retained (CFBridgingRetain) 将 Objective-C 指针转换为 Core Foundation 指针,并将所有权转移给您。您负责调用 CFRelease 或相关函数来放弃对象的所有权。
__bridge_transfer (CFBridgingRelease) 将非 Objective-C 指针移动到 Objective-C 并将所有权转移给 ARC。 ARC 负责放弃对象的所有权。
作为后续,在这种特定情况下,如果您使用的是 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) 强制转换,这仍然是避免编译器错误所必需的。