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メソッドと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!");
}
于 2012-09-11T18:15:15.303 に答える
1

そうかもしれないし、そうでないかもしれない。オブジェクトの割り当てが解除されると nil になります。testViewnilに設定したという事実は、オブジェクトを解放していることを意味するだけです。ただし、オブジェクトがすぐに割り当て解除されるとは限りません。

ここでの問題は、保持カウントに特定の値を想定していることです。alloc+init シーケンスによってカウント 1 のオブジェクトが得られたので、testViewnil に設定すると 0 になり、オブジェクトの割り当てが解除されると思います。

特定の保持カウントを仮定しないでください。常に相対的な保持カウントの観点から考える必要があります。alloc+init シーケンスは +1 オブジェクト (1 ではなく +1) を返します。settestViewを nil に設定すると、ARC が呼び出さreleaseれ、+0 オブジェクト (0 ではなく +0) に変わります。これは、まだアクセスできるという保証がないことを意味します。弱参照が有効な場合と無効な場合があります。

実際に起こっているのは、init メソッド (または親の連鎖した init メソッド) の内部で への呼び出しがあったautoreleaseため、オブジェクトの refcount はまだ 0 ではありません。次のプール排水。

編集:

また、彼の返信でアダムが言っていることも正しいです。

于 2012-09-11T18:15:46.347 に答える
0

Your testViewis local variable と ARC の下のローカル変数には、正確な有効期間のセマンティクスがありません。6.1 を読む:

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

どういう意味ですか?これは、コンパイラがやりたいことを何でもできることを意味します。

testView現在の実装では、メソッドの最後でオブジェクトが解放されます。しかし、オプティマイザー (今、未来、...) が有効期間が終了したと判断し、それをより早く (メソッドの終了前に) 解放する場合はどうなるでしょうか?

つまり、未定義の動作に依存しようとしています。これをしないでください、これに頼らないでください。この場合、オブジェクトが実際にいつ解放されるかはわかりません = 弱い参照がゼロになります。

于 2012-09-12T11:25:32.367 に答える