3

ブロックが強力な参照を作成せずに(したがって参照カウントをインクリメントせずに)ブロック内の「自己」(およびivars)を参照する正しい方法は何ですか?

たとえば、次のように'self'の参照カウントが増加することがわかりました。

^(id sender) {
    [self.navigationController popViewControllerAnimated:YES];
}

上記を回避するために、私は次のことを行ってきました。

__weak WhateverController *weakSelf = self;
^(id sender) {
    [weakSelf.navigationController popViewControllerAnimated:YES];
};

そして、はい、私はこれが擬似コードであることを理解しています。

4

2 に答える 2

10

また、self への間接参照も、self に保持を作成します。たとえば_ivar、インスタンス変数の場合、それにアクセスすると、self への暗黙的な参照になるため、次の例でも self が保持されます。

^(id sender) {
    [_ivar popViewControllerAnimated:YES];
}

さらに、あなたの例を拡張するためweakに、弱参照にメッセージを送信しても問題ありません。nil の場合、何も起こりません。そうでない場合、コンパイラは、メソッドの呼び出しによって参照が有効なままであることを保証するコードを生成します。

したがって、これで問題ありません。

__weak Foo *weakSelf = self;
^(id sender) {
    [weakSelf.foo doSomething];
}

foo は になるかnil、そうでないかのいずれかになるため、 の実行中ずっと非 nil のままであることが保証されますdoSomething

ただし、次の呼び出しは、中間呼び出しになる可能性があるため、お勧めselfできませんnil。これは、おそらく必要なものではありません。

__weak Foo *weakSelf = self;
^(id sender) {
    [weakSelf.foo doSomething];
    [weakSelf.foo doSomethingElse];
}

その場合、おそらくブロック内に独自の強い参照を作成して、ブロックの実行全体で一貫した値を保持する必要があります。

一方、弱い参照を介して iVar に直接アクセスする場合は、次のコードが原因で、弱い強いダンスを行う必要があります。

__weak Foo *weakSelf = self;
^(id sender) {
    weakSelf->_foo = bar;
}

あれば爆破しweakSelfますnil

したがって、上記の最後の 2 つの状況では、次のようなことを行います。

__weak Foo *weakSelf = self;
^(id sender) {
    Foo *strongSelf = weakSelf;
    if (!strongSelf) return;
    // Now, do anything with strongSelf, as it is guaranteed to be around
}

もちろん、iVar の状況は、実際に iVar に直接アクセスする場合にのみ問題になります...

于 2012-09-10T19:10:52.050 に答える
2

Apple の表記は sself ですが、それ以外は問題ありません。
アーク以外のプロジェクトでは、次のコードを使用して、「自己」がブロックによって保持されないようにします。
__block id sself = self

于 2012-09-10T18:29:45.047 に答える