1. ホーム
  2. objective-c

弱い参照と__ブロック参照の違いは何ですか?

2023-09-17 18:57:45

質問

Xcodeのドキュメントを読んでいて、不可解なことがあります。

__block typeof(self) tmpSelf = self;
[self methodThatTakesABlock:^ {
    [tmpSelf doSomething];
}];

以下はドキュメントからコピーしたものです。

ブロックは、それが捕捉する変数への強い参照を形成します。もしあなたが self を使うと、ブロックはその変数への強い参照を形成します。 self への強い参照を形成し、したがって、もし self がブロックへの強い参照を持つ場合(通常はそうです。 にもブロックへの強い参照がある場合 (通常そうです)、強い参照サイクルが発生します。このサイクルを避けるには を作成する必要があります。 __block のようにブロックの外側で self を参照するようにします。 を作成する必要があります。

私は何が 'a weak (or __block )』の意味がわからないのですが?

__block typeof(self) tmpSelf = self;

__weak typeof(self) tmpSelf = self;

こちらも全く同じ?

資料の中にもう一枚ありました。

注意: ガベージコレクションのある環境では、もしあなたが __weak__block という修飾子を変数につけた場合、ブロックはその変数を確実に生かしません。

というわけで、まったくもって困惑しています。

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

ブロックに関するドキュメントより

__block 変数は、変数の字句の範囲と、その字句の範囲内で宣言または作成されたすべてのブロックとブロックのコピーの間で共有されるストレージに格納されています。したがって、フレーム内で宣言されたブロックのコピーがフレームの終わりを過ぎても(例えば、後で実行するためにどこかに待機させられて)、ストレージはスタックフレームの破壊を生き延びます。与えられたレキシカルスコープ内の複数のブロックは、同時に共有変数を使用することができます。

__weakに関するドキュメントより

__weakは、参照されているオブジェクトを生かさない参照を指定します。弱い参照は、そのオブジェクトへの強い参照がない場合、nilに設定されます。

つまり、技術的に異なるものです。__block は外部スコープからブロックスコープに変数がコピーされないようにするためのものです。__weakは自分で区切る弱いポインタです。

技術的にと言ったのは、あなたの場合、これらは(ほとんど)同じことを行うからです。唯一の違いは、ARC を使用しているかどうかです。プロジェクトが ARC を使用し、iOS4.3 以降にのみ対応している場合は、__weak を使用します。これは、グローバルスコープの参照が何らかの理由で解放された場合、参照がnilに設定されることを保証します。ARCを使用していない場合や古いOSの場合は、__blockを使用してください。

ここには微妙な違いがあるので、しっかり理解しておきましょう。

EDIT: パズルへのもうひとつのピースは、__unsafe_unretainedです。この修飾子は__weakとほぼ同じですが、4.3以前のランタイム環境向けです。しかし、これはnilに設定されず、ぶら下がったポインターを残すことができます。