3

現在、次のようなコードの一部があります。

__strong MyRequest *this = self;

 MyHTTPRequestOperation *operation = [[MyHTTPRequestOperation alloc]initWithRequest:urlRequest];
 [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *request, id responseObject) {
     [this requestFinished:request];
 }
 failure:^(AFHTTPRequestOperation *request, NSError *error) {
     [this requestFailed:request withError:error];
 }];

他のいくつかのクラスがこのコードが配置されているクラスから継承し、独自の requestFinished および requestFailed を実装しているため、私は主にこれを行っています。

自己参照を __weak に変更すると、EXC_BAD_ACCESS エラーが発生し始めます。__strong 参照を使用すると、すべて正常に機能しますが、保持サイクルを作成することを恐れています。私はARCを使用していることに注意してください。

このコードは、問題を引き起こす保持サイクルを作成していますか? これに対する簡単な解決策はありますか?継承クラスが独自のメソッドを実装して応答を処理できるようにするために、私が従うことができる別のアプローチはありますか?

4

1 に答える 1

11

はい、保持サイクルが作成されます。それは問題を引き起こしますか?多分。

API がサポートしている場合は、ハンドラーをリセットできます。これにより、保持サイクルが手動で中断されます。

[operation setCompletionBlockWithSuccess:nil failure:nil];

または、弱い参照を使用できます。ただし、弱参照を試したところ、クラッシュしたとあなたは言います。弱参照は、メッセージの開始時に nil であるか、メッセージが処理されるまで有効であることが保証されています。言い換えれば、考慮してください...

__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    [weakSelf doSomething];
});

非同期ブロックの実行時に が nil の場合weakSelf、「何も起こりません」。nil でない場合、少なくともdoSomethingが終了するまで保持されることが保証されます。実際には、これは次のようになります。

__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    { id obj = weakSelf; [weakSelf doSomething]; obj = nil; }
});

ただし、これを行った場合は次の点に注意してください。

__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    [weakSelf doSomething];
    [weakSelf doSomethingElse];
});

doSomethingオブジェクトが と の間でnil になる可能性があることdoSomethingElse

さらに、弱参照を介してインスタンス変数にアクセスする場合は、SEGV を要求しているだけです。

__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    foo = weakSelf->someIVar; // This can go BOOM!
});

したがって、ハンドラーが単一のメッセージの弱い参照にアクセスしている場合は、問題ありません。それ以外は「弱い強いダンス」をするべきです。

__weak MyRequest *weakSelf = self;
dispatch_async(someQ, ^{
    MyRequest *strongSelf = weakSelf;
    if (!strongSelf) return;
    [strongSelf doSomething];
    [strongSelf doSomethingElse];
    foo = strongSelf->someIVar;
});

ガイドラインに従っていると思われる場合は、クラッシュの詳細を含むより完全なソースコードの例が役立つでしょう...

于 2012-10-15T18:48:52.020 に答える