2012-03-20 6 views
2

ブロックを使用して非ARCプロジェクトで非同期http要求の応答を処理しています。コードはこの(関連部分)のようになります。私はselfブロックの内側(ないselfのコピー)を変更できるようにObjective-Cで保持サイクルを起こさずにブロック内に変数を保持する

NSMutableUrlRequest* request = ...; 
__block typeof(self) mutableSelf = self; 

void (^didGetSessionBlock)(Gopher* newGopher) = ^(Gopher* newGopher) { 
    if (newGopher.statusCode == HTTP_OK) { 
     ... 
     mutableSelf.retryOnFail = NO; 
     [mutableSelf executeRequest:request]; 
    } 

    ... 
    [mutableSelf setStatusCode:newGopher.statusCode]; 
}; 

Gopher* newGopher = [[[Gopher alloc] init] autorelease]; 

[newGopher setDidCompleteBlock:didGetSessionBlock]; 
[newGopher fetchSession:myApp.settings.userName password:myApp.settings.password]; 

__block mutableSelfが使用されています。 __blockキーワードが正しく理解されていれば、mutableSelfが保持されていないので、ブロックが実行されているときにすでに解放されている可能性があります(これはまさに起こります)。

私は

[self executeRequest:request]; 

[mutableSelf executeRequest:request]; 

を変更した場合selfが保持されますと、ブロックが実行されるまで解放されませんので、すべてが順調です。ただし、selfを直接参照すると、保持サイクルによってリークが発生する可能性があります。

方法はありますか?それが宣言されたときに手作業でmutableSelfを保持し、それをブロック内で解放する必要がありますか?または、ブロック内でselfを使用して、私が変更していない場所にリークを作成する必要がありますか?コードが変更された場合、混乱や未来のバグを避けるため、どちらの亜種も脆弱で、コメントに説明が必要です。

この問題を解決する方法はありますか?そうでない場合、最良のアプローチは何ですか?

+0

[ブロックを使って自己保持](http://stackoverflow.com/questions/4352561/retain-cycle-on-self-with-blocks)とその回答をご覧ください。 –

答えて

3

ブロック内でselfを変更していない場合は、そのブロックが指すオブジェクトのみを変更します。私はあなたが必要とは思わない__block

+0

Aha。だから '__block'はスタック変数を変更したいときだけ必要です。また、 'self'に' __block'を使わないと、保持サイクルの問題をどのように受け継がれますか? – aspartame

関連する問題