只是想完全理解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 ???
谢谢!
答案 0 :(得分:7)
addObserver
方法似乎是retain
和autorelease
视图。这就是为什么弱参考在初始参考被填充之后不会归零。只需在调试器中运行此代码:
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
对象。但是如果优化器(现在,将来......)决定生命周期结束并且它会更快地(在方法结束之前)释放它会怎么样?
换句话说,你试图依赖未定义的行为。不要这样做,不要依赖于此。在这种情况下,您永远不知道对象何时被释放=弱引用为零。