ARC 和桥接演员

发布于 2024-11-28 23:50:43 字数 1162 浏览 1 评论 0原文

使用 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 type T. If T
is a retainable object pointer type, then op must have a
non-retainable pointer type. If T 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 CGColorRefs. My guess is that I should use __brige here, but exactly why I should (or should not) is unclear.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

零時差 2024-12-05 23:50:43

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

  • (__bridge_transfer) opCFBridgingRelease(op) 用于消耗保留- 将 CFTypeRef 传输到 ARC 时的计数。这也可以用 id someObj = (__bridge) op; 来表示。 CFRelease(op);

  • (__bridge_retained) opCFBridgingRetain(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 alternatively CFBridgingRelease(op) is used to consume a retain-count of a CFTypeRef while transferring it over to ARC. This could also be represented by id someObj = (__bridge <NSType>) op; CFRelease(op);

  • (__bridge_retained <CFType>) op or alternatively CFBridgingRetain(op) is used to hand an NSObject over to CF-land while giving it a +1 retain count. You should handle a CFTypeRef you create this way the same as you would handle a result of CFStringCreateCopy(). This could also be represented by CFRetain((__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.

┈┾☆殇 2024-12-05 23:50:43

我在 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

无畏 2024-12-05 23:50:43

作为后续,在这种特定情况下,如果您使用的是 iOS,Apple 建议使用 UIColor 及其 -CGColor 方法将 CGColorRef 返回到 colors NSArray 中。在过渡到 ARC 发行说明中,在“编译器处理从 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) 转换,这仍然是避免编译器错误所必需的。

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 the colors 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:

CAGradientLayer *gradientLayer = (CAGradientLayer *)[self layer];
gradientLayer.colors = [NSArray arrayWithObjects:(id)[[UIColor darkGrayColor] CGColor],
                                                 (id)[[UIColor lightGrayColor] CGColor], nil];

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文