1. ホーム
  2. objective-c

[解決済み] ブロックを使って `self` のサイクルを保持する

2022-04-23 14:56:11

質問

この質問はかなり基本的なもので、恐縮ですが、ブロックに入りつつある多くのObjective-Cプログラマに関係するものだと思います。

ブロックは、その中で参照されるローカル変数を「ブロック」として捕捉するため、「ブロック」を「ブロック」と呼ぶと聞いたことがあります。 const コピーを使用すると self をブロック内で使用すると、そのブロックがコピーされたときに、retain cycleが発生する可能性があります。ですから、私たちは __block を直接処理するようにブロックに強制します。 self コピーされるのではなく

__block typeof(self) bself = self;
[someObject messageWithBlock:^{ [bself doSomething]; }];

ではなく、単に

[someObject messageWithBlock:^{ [self doSomething]; }];

私が知りたいのは次のようなことです。もしこれが本当なら、(GCの使用は別として)醜態をさらすことを避ける方法はあるのでしょうか?

どのように解決するのですか?

厳密には、constコピーであることはこの問題とは関係ありません。ブロックは、作成時に取り込まれたobj-c値を保持します。たまたま、const-copyの問題の回避策はretainの問題の回避策と同じです。 __block のストレージクラスがあります。

いずれにせよ、あなたの質問に答えるなら、ここに本当の代替案はありません。もしあなたが独自のブロックベースのAPIを設計していて、そうすることに意味があるのなら、ブロックに self を引数として与えます。残念ながら、これはほとんどのAPIで意味をなさない。

ivarを参照する場合も全く同じ問題がありますので、ご注意ください。ブロック内でivarを参照する必要がある場合は、代わりにプロパティを使用するか、または bself->ivar .


追記:ARCとしてコンパイルする場合。 __block は、retain cycles を壊さなくなりました。ARC用にコンパイルしている場合は __weak または __unsafe_unretained の代わりに