ARC 和桥接演员
使用 ARC,我无法再将 CGColorRef
转换为 id
。我了解到我需要进行桥接演员。根据 clang 文档:
桥接转换是使用以下三个关键字之一进行注释的 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
数组。我的猜测是我应该在这里使用 __brige
,但到底为什么我应该(或不应该)还不清楚。
With ARC, I can no longer cast CGColorRef
to id
. I learned that I need to do a bridged cast. According clang docs:
A bridged cast is a C-style cast annotated with one of three keywords:
(__bridge T) op
casts the operand to the destination typeT
. IfT
is a retainable object pointer type, thenop
must have a
non-retainable pointer type. IfT
is a non-retainable pointer type,
then op must have a retainable object pointer type. Otherwise the cast
is ill-formed. There is no transfer of ownership, and ARC inserts no
retain operations.
(__bridge_retained T) op
casts the operand, which must have
retainable object pointer type, to the destination type, which must be
a non-retainable pointer type. ARC retains the value, subject to the
usual optimizations on local values, and the recipient is responsible
for balancing that +1.
(__bridge_transfer T) op
casts the operand, which must have
non-retainable pointer type, to the destination type, which must be a
retainable object pointer type. ARC will release the value at the end
of the enclosing full-expression, subject to the usual optimizations
on local values.These casts are required in order to transfer objects in and out of
ARC control; see the rationale in the section on conversion of
retainable object pointers.Using a
__bridge_retained
or__bridge_transfer
cast purely to convince
ARC to emit an unbalanced retain or release, respectively, is poor
form.
In what kind of situations would I use each?
For example, CAGradientLayer
has a colors
property which accepts an array of CGColorRef
s. My guess is that I should use __brige
here, but exactly why I should (or should not) is unclear.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我同意这个描述令人困惑。由于我刚刚掌握了它们,我将尝试总结一下:
(__bridge_transfer) op
或CFBridgingRelease(op)
用于消耗保留- 将CFTypeRef
传输到 ARC 时的计数。这也可以用 id someObj = (__bridge(__bridge_retained) op
或CFBridgingRetain(op)
用于传递NSObject< /code> 转移到 CF-land,同时给它 +1 保留计数。您应该像处理
CFStringCreateCopy()
的结果一样处理以此方式创建的CFTypeRef
。这也可以用 CFRetain((__bridge CFType)op); 来表示。 CFTypeRef someTypeRef = (__bridge CFType)op;__bridge
只是在指针域和 Objective-C 对象域之间进行转换。如果您不想使用上面的转换,请使用这个。也许这很有帮助。就我个人而言,与普通的强制转换相比,我更喜欢
CFBridging...
宏。I agree that the description is confusing. Since I just grasped them, I'll try to summarize:
(__bridge_transfer <NSType>) op
or alternativelyCFBridgingRelease(op)
is used to consume a retain-count of aCFTypeRef
while transferring it over to ARC. This could also be represented byid someObj = (__bridge <NSType>) op; CFRelease(op);
(__bridge_retained <CFType>) op
or alternativelyCFBridgingRetain(op)
is used to hand anNSObject
over to CF-land while giving it a +1 retain count. You should handle aCFTypeRef
you create this way the same as you would handle a result ofCFStringCreateCopy()
. This could also be represented byCFRetain((__bridge CFType)op); CFTypeRef someTypeRef = (__bridge CFType)op;
__bridge
just casts between pointer-land and Objective-C object-land. If you have no inclination to use the conversions above, use this one.Maybe this is helpful. Myself, I prefer the
CFBridging…
macros quite a bit over the plain casts.我在 iOS 文档中找到了另一种我认为更容易理解的解释:
__bridge
在 Objective-C 和 Core Foundation 之间传输指针,但不转移所有权。__bridge_retained (CFBridgingRetain)
将 Objective-C 指针转换为 Core Foundation 指针,并将所有权转让给您。您负责调用 CFRelease 或相关函数来放弃对象的所有权。
__bridge_transfer (CFBridgingRelease)
将非 Objective-C 指针移至 Objective-C,并将所有权转让给 ARC。ARC 负责放弃对象的所有权。
来源: 免费桥接类型
I found another explanation in the iOS documentation that I think is easier to understand:
__bridge
transfers a pointer between Objective-C and Core Foundation with no transfer of ownership.__bridge_retained (CFBridgingRetain)
casts an Objective-C pointer to a Core Foundation pointer and also transfers ownership to you.You are responsible for calling CFRelease or a related function to relinquish ownership of the object.
__bridge_transfer (CFBridgingRelease)
moves a non-Objective-C pointer to Objective-C and also transfers ownership to ARC.ARC is responsible for relinquishing ownership of the object.
Source: Toll-Free Bridged Types
作为后续,在这种特定情况下,如果您使用的是 iOS,Apple 建议使用 UIColor 及其
-CGColor
方法将 CGColorRef 返回到colors
NSArray 中。在过渡到 ARC 发行说明中,在“编译器处理从 Cocoa 方法返回的 CF 对象”部分下,指出使用像-CGColor
这样返回 Core Foundation 对象的方法将自动由编译器正确处理。因此,他们建议使用如下代码:
请注意,截至目前,Apple 的示例代码缺少我上面的 (id) 转换,这仍然是避免编译器错误所必需的。
As a follow-on, in this specific case, if you are on iOS, Apple recommends using UIColor and its
-CGColor
method to return the CGColorRef into thecolors
NSArray. In the Transitioning to ARC Release Notes, under the section "The Compiler Handles CF Objects Returned From Cocoa Methods", it is indicated that using a method like-CGColor
which returns a Core Foundation object will automatically be handled properly by the compiler.Thus, they suggest using code like the following:
Note that as of right now, Apple's example code is missing the (id) cast I have above, which is still necessary to avoid a compiler error.