0

私のクラスが次のように見えるとしましょう

@interface MyClass {
    MyObject* _object;
    dispatch_queue_t _queue;
}
-(void)myBlocksUsingMethod;
@end

キューの初期化のセマンティクスを無視して、実装します

-(void)myBlockUsingMethod {
    dispatch_async(_queue, ^{
        [_object doSomething];
    });
}

上記のコードが示すように、ブロック内に自己を保持しても問題ありませんか?

ブロックを次のように書き換えることができます

-(void)myBlockUsingMethod {
    __weak MyClass* weakSelf = self;
    dispatch_async(_queue, ^{
        MyClass* strongSelf = weakSelf;
        [strongSelf._object doSomething];
    });
}

しかしstrongSelf == nil、この状況で my_queueが保持しているオブジェクトの iVar であるかどうかをテストする必要があるでしょうか?

また、私のメソッドが参照する別のブロックを同じキューdoSomethingにプッシュするとどうなりますか? selfそれは保持サイクルを引き起こしますか?

4

2 に答える 2

2

タイトルの質問に答えるには: はい、これを行う理由はたくさんあります。オブジェクトがブロックよりも長く存続することが確実にわかっている場合や、後で特定の時間に手動で破棄される保持サイクルを作成したい場合があります。

ただし、コードでは、かなり間違ったことをしています。最初のメソッド (self への暗黙的な強い参照を作成するメソッド) は、警告を生成する必要があります。

2 番目のものはコンパイルされません。あなたはこれを持っています:

[strongSelf._object doSomething];

という名前のプロパティを呼び出していますが_object、そうではないかと思います。だから、多分あなたはこれを意味しました:

[strongSelf.object doSomething];

その場合、 に送信されたメッセージはstrongSelf事実上何もしないため、問題ありません。nilnil

または、プロパティがない場合は、おそらく次のことを意味します。

[strongSelf->_object doSomething];

この場合、strongSelf が nil の場合、これはメッセージを送信するのではなくnil、null ポインターを逆参照するため、プログラムは失敗します。後者を行う場合は、nil明示的に確認する必要があります。

_queueブロック内ではアクセスしないので、そのアクセスは問題ありません。ブロック内の iVar に直接アクセスする場合は、保持サイクルを作成してオブジェクトがまだ生きていることを確認するか、弱-強-ダンスを再生して nil をチェックする必要があります。

オブジェクトを複数の行で使用する場合は、weak-strong-dance も実行する必要があります。これは、weak オブジェクトがアクセス間で解放される可能性があるためです (ランタイムは、__weak が nil ではなく、メッセージを受け入れる場合、それが保持されることを保証します)。そのメッセージが処理されるまで有効です)。

[weakObject message1];
// weakObject can become nil here
[weakObject message2];
于 2012-09-07T22:58:33.707 に答える
0

保持サイクルは一時的なものであるため、問題ないはずです。ディスパッチされたアクションが実行されると、キューから削除されるため、ブロックを保持するものはなくなります。

于 2012-09-07T22:40:49.803 に答える