ARC 可以与 Core Graphics 对象一起使用吗?

发布于 2024-12-10 17:04:11 字数 345 浏览 0 评论 0原文

我最近开始了一个使用自动引用计数 (ARC) 的新项目。
当我分配 CALayer 的内容时:

UIView* view = ...
UIImage* image = ...
view.layer.contents = image.CGImage

我收到错误

ARC 不允许将非 Objective-C 指针类型“CGImageRef”隐式转换为“id”

简单地将 CGImageRef 转换为 id 会隐藏错误,但我想知道那么 ARC 是否还能正常工作呢?

I recently started a new project using Automatic Reference Counting (ARC).
When I assigned the contents of a CALayer:

UIView* view = ...
UIImage* image = ...
view.layer.contents = image.CGImage

I got an error

Implicit conversion of a non-Objective-C pointer type 'CGImageRef' to 'id' is disallowed with ARC

Simply casting the CGImageRef to id hides the error, but I was wondering if the ARC still functions correctly then?

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

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

发布评论

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

评论(3

空城缀染半城烟沙 2024-12-17 17:04:11

您确实应该查看 WWDC 2011 的 ARC 视频。它们可以在开发者网站上找到并通过 iTunes 打开。尤其:

• 会议 323 – 介绍自动引用计数

• 会议 322 – Objective-C 的深入进展

另外,ARC 参考说明:

https://developer.apple。 com/library/content/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html

参考说明和视频都讨论了 Core Graphics(等)以及它们如何使用弧。

具体来说,请查看“管理免费桥接”部分

在许多 Cocoa 应用程序中,您需要使用 Core Foundation 风格的对象,无论是来自 Core Foundation 框架本身(例如
CFArrayRef 或 CFMutableDictionaryRef)或来自采用的框架
核心基础约定,例如核心图形(您可以使用类型
如 CGColorSpaceRef 和 CGGradientRef)。

编译器不会自动管理Core的生命周期
基础物体;您必须调用 CFRetain 和 CFRelease (或
相应的类型特定变体)由核心规定
基础内存管理规则(参见内存管理编程
核心基础指南)。

如果您在 Objective-C 和 Core Foundation 风格的对象之间进行转换,您
需要告诉编译器该对象的所有权语义
使用强制转换(在 objc/runtime.h 中定义)或 Core
基础风格宏(在 NSObject.h 中定义):[...]

Jörg Jacobsen 对桥接选项也有很好的总结概述:在 ARC 环境中管理免费桥接

__bridge_retained (注意:仅在从对象指针转换为 C 类型指针时使用它):我(程序员)需要引用该对象
在 C 类型指针的黑暗世界中有一段时间,这是不透明的
你,ARC。所以请不要在我还在的时候释放这个对象
需要它。我(程序员)保证自己发布(在黑暗中)
世界)当我完成它时

__bridge_transfer (注意:仅在从 C 类型指针转换为对象指针时使用它):我(程序员)将其交给你,ARC,一个
我拥有的、我在黑暗中不再感兴趣的物体
C 类型指针的世界对你来说是不透明的。每当你,ARC,
完成该对象后请自行释放它,因为您知道
正确的时间,从而节省我一些工作,而不必自己做。

__bridge:ARC,你一直在平衡你的保留和释放,就像我在 C 类型指针的黑暗世界中不断平衡我的一样。
是…。每当我需要在黑暗世界中抓住一个物体时,我就会
我自己保留它并在适当的时候释放它。我不需要任何
与你签订额外合同,ARC。

You should really check out the ARC videos from WWDC 2011. They are available on the developer site and open through iTunes. Especially:

• Session 323 – Introducing Automatic Reference Counting

• Session 322 – Objective-C Advancements in Depth

Also, the ARC reference notes:

https://developer.apple.com/library/content/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html

Both the reference notes and the videos discuss Core Graphics (et al) and how they work with ARC.

Specifically, look at the section called "Managing Toll-Free Bridging"

In many Cocoa applications, you need to use Core Foundation-style objects, whether from the Core Foundation framework itself (such as
CFArrayRef or CFMutableDictionaryRef) or from frameworks that adopt
Core Foundation conventions such as Core Graphics (you might use types
like CGColorSpaceRef and CGGradientRef).

The compiler does not automatically manage the lifetimes of Core
Foundation objects; you must call CFRetain and CFRelease (or the
corresponding type-specific variants) as dictated by the Core
Foundation memory management rules (see Memory Management Programming
Guide for Core Foundation).

If you cast between Objective-C and Core Foundation-style objects, you
need to tell the compiler about the ownership semantics of the object
using either a cast (defined in objc/runtime.h) or a Core
Foundation-style macro (defined in NSObject.h): [...]

Jörg Jacobsen has a good summary overview of the bridging options as well: Managing Toll-free Bridging in an ARC’ed Environment.

__bridge_retained (n.b.: only use it when casting from object pointer to C type pointer): I (the programmer) need to reference this object
for some time in the dark world of C type pointers which is opaque to
you, ARC. So please, please do not release this object while I still
need it. I (the programmer) promise to release it myself (in the dark
world) when I’m done with it

__bridge_transfer (n.b.: only use it when casting from C type pointer to object pointer): I (the programmer) hand over to you, ARC, an
object that I own and that I am no longer interested in in the dark
world of C type pointers that is opaque to you. Whenever you, ARC, are
done with that object please release it yourself, because you know the
right time and thus save me some work not having to do it myself.

__bridge: ARC, you keep balancing out your retains and releases as I keep balancing out mine in the dark world of C type pointers which
is…. Whenever I need to hold on to an object in the dark world I will
retain it myself and release it when appropriate. I don’t need any
extra contract with you, ARC.

倾城泪 2024-12-17 17:04:11

尽管史蒂夫指出了参考文献,但我相信您上面展示的案例可能很特殊。来自过渡到 ARC 发行说明,注意“编译器处理从 Cocoa 方法返回的 CF 对象”一节:

编译器理解返回 Core 的 Objective-C 方法
基础类型遵循历史上的 Cocoa 命名约定(参见
高级内存管理编程指南)。例如,
编译器知道,在 iOS 中,由 CGColor 返回的 CGColor
UIColor 的方法不被拥有。

他们提供的代码示例:

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

依赖于这些方法已知的 CGColors 返回(它们缺少我在上面代码中添加的 id 的转换,这应该很快在他们的文档中得到纠正)。

因为 [image CGImage] 遵循命名约定,所以我相信 CGImage 会在这里正确桥接。我认为你的 id 转换应该就是你所需要的。

Despite the references pointed out by Steve, I believe the case you show above might be special. From the Transitioning to ARC Release Notes, pay attention to the section "The Compiler Handles CF Objects Returned From Cocoa Methods":

The compiler understands Objective-C methods that return Core
Foundation types follow the historical Cocoa naming conventions (see
Advanced Memory Management Programming Guide). For example, the
compiler knows that, in iOS, the CGColor returned by the CGColor
method of UIColor is not owned.

The code example they provide:

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

relies on the known return of CGColors from these methods (they are missing the cast to id that I've added in the above code, which should be corrected in their documentation soon).

Because [image CGImage] follows the naming conventions, I believe the CGImage will be bridged properly here. I think that your cast to id should be all that you need here.

梅倚清风 2024-12-17 17:04:11

对于layer.contents = (id)image.CGImage问题的一个流行答案是layer.contents = obj_unretainedObject(image.CGImage)

我做=(__bridge id)image.CGImage

One popular answer to layer.contents = (id)image.CGImage question is layer.contents = obj_unretainedObject(image.CGImage).

I do =(__bridge id)image.CGImage.

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