【发布时间】:2014-11-21 13:05:51
【问题描述】:
我有一个关于以下代码的问题:
@interface ViewController ()
@property (nonatomic, weak) CALayer *someLayer;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.someLayer = [CALayer layer];
self.someLayer.frame = CGRectMake(10.0, 10.0, 100.0, 100.0);
self.someLayer.backgroundColor = [UIColor yellowColor].CGColor;
[self.view.layer addSublayer:self.someLayer];
}
@end
据我了解,[CALayer layer] 应该返回一个自动释放的值,只要方法调用正在进行,它就应该存在。然后它被弱属性someLayer 引用。
由于该层后来被视图层保留,所以一切都应该没问题,并且该层应该出现。
它的作用,但仅适用于
在较新的设备上,该图层不会显示。 将 property 属性更改为 strong 可以解决问题,但我想知道为什么该图层会立即释放。
您是否有任何提示我可以调试此行为以查看发生了什么变化?
谢谢!
更新:
使用self.someLayer = [CALayer [alloc]] init] 会给出适当的警告
这是我理解的,因为在使用 alloc 时,该值归调用者所有。由于所有者不保留价值,因此没有强参考。
像layer 这样的便利初始化程序应该自动释放一个保留值,在自动释放池耗尽之前应该可以访问它。在这种情况下,Xcode 也没有警告。
更新 #2: 变得更有趣了…… 我在装有 iOS 8 的 iPhone 6 和装有 iOS 6 的 iPhone 4 上测试了代码。 图层不会显示在它们上面...
但是
如果我在创建的行设置断点并越过它,该层将在模拟器
我怎样才能检查引擎盖下发生了什么?
更新 #3 和更多解释:
Big Nerd Ranch 上有一篇关于这种行为的精彩文章 ARC Gotcha - Unexpectedly Short Lifetimes
查看上面代码的反汇编显示了 ARC 如何插入_objc_retainAutoreleasedReturnValue
来自文章:
您可以看到正在使用 ARC 的“避免自动释放池”优化:如果一个方法返回一个自动释放的对象,并且调用者不需要挂在它上面,ARC 可以避免访问自动释放池。该方法将返回一个保留对象,而 objc_retainAutoreleasedReturnValue 将处理它。
所以,为了避免这个问题,要么声明一个强属性(正如我上面提到的),要么看看@graver 的答案。
【问题讨论】:
-
ARC 已开启?很奇怪,也许你应该在设备上调试。我不相信模拟器。
标签: ios objective-c core-animation automatic-ref-counting