arc,强弱实例变量

时间:2012-09-11 17:45:18

标签: objective-c automatic-ref-counting

只是想完全理解ARC。

MyView *testView = [[MyView alloc] init];

__weak MyView *weakView = testView;

[weakView addObserver:self forKeyPath:@"alpha" options:0 context:nil];

testView = nil;

if(weakView) {
     NSLog(@"WeakView exists!");
}

我不明白为什么我的NSLog语句正在打印。因为weakView是对testView的弱引用,所以一旦testView设置为nil就不应该指向nil ???

谢谢!

3 个答案:

答案 0 :(得分:7)

addObserver方法似乎是retainautorelease视图。这就是为什么弱参考在初始参考被填充之后不会归零。只需在调试器中运行此代码:

UIView *testView = [[UIView alloc] init];

__weak UIView *weakView = testView;

@autoreleasepool {
    [weakView addObserver:self forKeyPath:@"alpha" options:0 context:nil];
}

testView = nil;

if(weakView) {
    NSLog(@"WeakView exists!");
}

答案 1 :(得分:1)

可能会也可能不会。当对象被释放时,它变为零。将testView设置为nil这一事实仅表示您正在释放该对象。但是不能保证该对象立即被释放。

这里的问题是您假设保留计数的给定值。您认为alloc + init序列为您提供了一个计数为1的对象,因此当您将testView设置为nil时,它将变为0并且该对象将被释放。

你应该从不假设给定的保留计数。你应该总是考虑相对保留计数。 alloc + init序列返回+1对象(不是1而是+1)。将set testView设置为nil ARC调用release并将其设置为+0对象(不是0,而是+0)时。这意味着您无法保证它仍然可以访问。您的弱参考可能有效也可能无效。

实际上发生的事情是,在init方法内部(或父项的链接init方法)已经调用autorelease,因此你的对象还没有引用的引用数。它将在下一个游泳池排水管处获取(并取消分配)。

编辑:

亚当在回答中所说的也是正确的。

答案 2 :(得分:0)

您的testView是局部变量,ARC下的局部变量没有精确的生命周期语义。阅读6.1:

http://clang.llvm.org/docs/AutomaticReferenceCounting.html#optimization.precise

这是什么意思?这意味着编译器可以做任何想做的事情。

当前实现在方法结束时释放testView对象。但是如果优化器(现在,将来......)决定生命周期结束并且它会更快地(在方法结束之前)释放它会怎么样?

换句话说,你试图依赖未定义的行为。不要这样做,不要依赖于此。在这种情况下,您永远不知道对象何时被释放=弱引用为零。