ブロックを使用して非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
を使用して、私が変更していない場所にリークを作成する必要がありますか?コードが変更された場合、混乱や未来のバグを避けるため、どちらの亜種も脆弱で、コメントに説明が必要です。
この問題を解決する方法はありますか?そうでない場合、最良のアプローチは何ですか?
[ブロックを使って自己保持](http://stackoverflow.com/questions/4352561/retain-cycle-on-self-with-blocks)とその回答をご覧ください。 –