对于CF类型,带有__attribute __((NSObject))的强大@property不会保留

Pat*_*pel 21 objective-c core-foundation ios automatic-ref-counting

更新:此问题已在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));
Run Code Online (Sandbox Code Playgroud)

其中两次打印"1".

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

Rob*_*ier 34

EDIT2(2013年3月)对于那些对此技术感兴趣的人,对于clang的ARC文档包括以下注释:

__attribute__((NSObject))不建议使用typedef.如果绝对有必要使用此属性,请非常明确地使用typedef,并且不要假设它将由__typeofC++模板参数替换等语言功能保留.

合理

从类型中偶然地剥离类型"sugar"的任何编译器操作都将产生没有属性的类型,这可能导致意外行为.


编辑以下是有趣的,但可能无关紧要.这是一个错误,你应该打开一个雷达.正如@lnafziger所指出的那样,这是合法的,应该受到尊重.错误是当你包括它时它没有被尊重nonatomic.如果你删除nonatomic,那么它的工作原理.nonatomic定义中没有任何内容表明这是设计上的.


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

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

可保留对象指针(或可保留指针)是可保留对象指针类型的值(可保留类型).有三种可保留的对象指针类型:

  • 块指针(通过将插入符号(^)声明符sigil应用于函数类型而形成)
  • Objective-C对象指针(id,Class,NSFoo*等)
  • typedef标有__attribute __((NSObject))

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

typedef __attribute__((NSObject)) CFStringRef MYStringRef;

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

... the rest of your code ...
Run Code Online (Sandbox Code Playgroud)

这将打印"1",然后打印"2",因为我认为你期望.因为未指明的原因让我害怕,但看着汇编输出,一切似乎都很好,我想不出任何具体问题或违规行为.

你可能有理由为此打开雷达.即使记录在案,但typedef未被处理为与指定类型相同的事实至少令人惊讶.

编辑:注意来自ObjC编程语言的 @ lnafziger的评论,无论是ARC规范/实现中的错误还是链接文档中的错误,都应该修复其中一个.

  • 打开雷达.很高兴你能找到它的工作条件顺便说一句. (5认同)
  • 如果您打开雷达,请在此处发布#. (2认同)