【问题标题】:strong @property with __attribute__((NSObject)) for a CF type doesn't retainCF 类型的带有 __attribute__((NSObject)) 的强 @property 不保留
【发布时间】:2012-03-13 13:31:50
【问题描述】:

更新:从 Xcode 4.6 开始,此问题已得到修复!

此技术现在再次按预期工作。但是,在您在代码中使用它之前,请务必阅读 Rob Napier 出色答案顶部的注释。

原帖

(ARC,Xcode 4.3.1,iOS 5.1)

我有一个强大的 CF 类型 (CGImage) 属性,我想由 ARC 使用 __attribute__((NSObject)) 自动管理它(如在合成的 setter 中保留和释放,并在 dealloc 中被取消),但它不起作用:我分配属性时不会保留对象。

重现的最小示例:

@interface TestClass : NSObject
@property (nonatomic, strong) __attribute__((NSObject)) CFStringRef str;
@end

// ...In some function
CFStringRef str = (__bridge CFStringRef)[NSString stringWithFormat:@"%g", 2.5];
NSLog(@"%ld", CFGetRetainCount(str));
TestClass *obj = [[TestClass alloc] init];
obj.str = str;
NSLog(@"%ld", CFGetRetainCount(str));

两次打印“1”。

现在奇怪的是(虽然我不确定)我认为它在我更新到 iOS 5.1 和 Xcode 4.3.1(来自 iOS 5 和 Xcode 4.2)之前工作正常,并从 gdb 切换到 lldb。没有升级(或知道如何改回编译器)的人可以确认一下吗?

【问题讨论】:

  • 一种解决方案就是使用NSString * 属性,并在分配时使用__bridge 强制转换。
  • 我没有从this link得到任何东西,希望你能得到一些东西
  • 不幸的是,这只是一个重现的例子,在我使用的实际代码中,我有一个 CGImage。我会编辑帖子。
  • 是的,这是真的,而且在 ARC 上也是如此,即使在 Mac 上也是如此:skitch.com/adib/8st94/arc-bug-on-corefoundation
  • 似乎在 OS X 10.8.2 下的 Xcode 4.6 中已修复。编译器生成一个对objc_setProperty_nonatomic 的调用,它将objc_retain 预期的新值。有人可以确认 iOS 6.1 吗?

标签: objective-c ios automatic-ref-counting core-foundation


【解决方案1】:

EDIT2(2013 年 3 月)仅供对这项技术感兴趣的人参考,ARC documentation for clang 包含以下说明:

不推荐使用__attribute__((NSObject)) typedefs。如果绝对需要使用此属性,请非常明确地使用 typedef,并且不要假设它会被 __typeof 和 C++ 模板参数替换等语言特性保留。

基本原理

任何偶然从类型中剥离类型“糖”的编译器操作都会生成没有该属性的类型,这可能会导致意外行为。


编辑 以下内容很有趣,但可能无关紧要。这是一个错误,您应该打开雷达。正如@lnafziger 所指出的,这是合法的,应该得到尊重。错误是当您包含nonatomic 时,它不会被兑现。如果您删除nonatomic,那么它可以工作。 nonatomic 定义中没有任何内容表明这是设计使然。


这有点聪明,但我想我明白为什么它不起作用了。顺便说一句,您可以通过生成汇编程序并注意setStr: 不调用objc_storeStrong() 来确认它不起作用。它做了一个简单的分配。

问题是您的属性定义不符合可保留对象指针的定义(强调添加):

可保留对象指针(或可保留指针)是 可保留对象指针类型(retainable type)。有三种 可保留对象指针类型的种类:

  • 块指针(通过将插入符号 (^) 声明符符号应用于 函数类型)
  • Objective-C 对象指针(id、Class、NSFoo* 等)
  • typedefs 标记为 __attribute__((NSObject))

您是否按照指定创建了 typedef?不,你没有。好的,那我们该怎么做呢?

typedef __attribute__((NSObject)) CFStringRef MYStringRef;

@interface TestClass : NSObject
@property (nonatomic, strong) MYStringRef str;
@end

... the rest of your code ...

这将打印“1”,然后是“2”,正如我假设您所期望的那样。由于不明原因让我害怕,但看看汇编程序的输出,一切似乎都很好,我想不出任何具体的问题或违规行为。

您可能有理由为此打开雷达。 typedef 不被视为与指定类型相同的事实至少令人惊讶,即使已记录在案。

编辑:注意到@lnafziger 来自ObjC Programming Language 的评论,ARC 规范/实现中肯定存在错误或链接文档中存在错误,因此应该修复其中一个。

【讨论】:

  • 打开了雷达。太好了,您能够找到它确实起作用的条件。
  • 如果您确实打开了雷达,请在此处发布#。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-09
  • 2011-06-09
  • 1970-01-01
  • 2021-10-30
  • 1970-01-01
  • 2011-08-02
  • 1970-01-01
相关资源
最近更新 更多