3

只是想完全理解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吗?

谢谢!

4

3 回答 3

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!");
}
于 2012-09-11T18:15:15.303 回答
1

它可能会也可能不会。当对象被释放时它变为 nil。您设置为 nil 的事实testView仅意味着您正在释放该对象。但是不能保证该对象会立即被释放。

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

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

实际上发生的事情是,在 init 方法(或父级的链式 init 方法)内部有一个调用,autorelease因此您的对象的引用计数还没有 0。它将在下一个游泳池排水管。

编辑:

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

于 2012-09-11T18:15:46.347 回答
0

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

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

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

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

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

于 2012-09-12T11:25:32.367 回答