__weak参照と__block参照の違いは何ですか?


80

Xcodeのドキュメントを読んでいますが、これが私を困惑させるものです。

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

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

ブロックは、キャプチャする変数への強力な参照を形成します。selfブロック内で使用する場合 、ブロックはへの強い参照を形成するため、ブロックへの強い参照もselfある場合 self(通常はそうなります)、強い参照サイクルが発生します。サイクルを回避する__blockには、上記の例のように、ブロックの外側に自分自身への弱い(または)参照を作成する必要があります。

「弱い(または__block)」の意味がわかりませんか?

です

__block typeof(self) tmpSelf = self;

そして

__weak typeof(self) tmpSelf = self;

ここでもまったく同じですか?

ドキュメントで別の部分を見つけました:

注:ガベージコレクション環境では、変数に__weak__block修飾子の両方を適用すると 、ブロックはそれが存続することを保証しません。

だから、私は完全に困惑しています。

回答:


109

__blockに関するドキュメントから

__block変数は、変数の字句スコープと、変数の字句スコープ内で宣言または作成されたすべてのブロックおよびブロックコピーの間で共有されるストレージに存在します。したがって、フレーム内で宣言されたブロックのコピーがフレームの終わりを超えて存続する場合(たとえば、後で実行するためにどこかにキューに入れられることによって)、ストレージはスタックフレームの破壊に耐えます。特定の字句スコープ内の複数のブロックは、共有変数を同時に使用できます。

__weakに関するドキュメントから

__weakは、参照されたオブジェクトを存続させない参照を指定します。オブジェクトへの強い参照がない場合、弱い参照はnilに設定されます。

したがって、それらは技術的に異なるものです。__blockは、変数が外部スコープからブロックスコープにコピーされるのを停止します。__weakは、自己区切りの弱いポインターです。

私が技術的に言ったことに注意してください。あなたの場合、彼らは(ほぼ)同じことをするからです。唯一の違いは、ARCを使用しているかどうかです。プロジェクトでARCを使用し、iOS4.3以降専用の場合は、__ weakを使用します。グローバルスコープ参照が何らかの方法でリリースされた場合、参照がnilに設定されるようにします。プロジェクトでARCを使用していない場合、または古いOSバージョン用の場合は、__ blockを使用してください。

ここには微妙な違いがあります。必ず理解してください。

編集:パズルのもう1つのピースは__unsafe_unretainedです。この修飾子は__weakとほぼ同じですが、4.3より前のランタイム環境用です。ただし、nilに設定されていないため、ポインタがぶら下がっている可能性があります。


1
これは、ARCを使用するiOS7にも引き続き適用できますか?プロファイラーを実行しましたが、__ blockまたは__weakを使用せず、ブロック内で自己を参照していなくても、コントローラーが解放されていることがわかります。
ジェイQ.


1
一緒に使ってみませんか?__block _weak NSString *strEg;
Cyber​​Mew 2016

5

手動参照カウントモードでは、__ block id x; xを保持しないという効果があります。ARCモードでは、__ block id x; デフォルトではxを保持します(他のすべての値と同じように)。ARCでの手動参照カウントモードの動作を取得するには、__ unsafe_unretained __block idx;を使用できます。ただし、__ unsafe_unretainedという名前が示すように、保持されていない変数を持つことは危険であり(ぶら下がる可能性があるため)、したがって推奨されません。2つのより良いオプションは、__ weakを使用するか(iOS4またはOSX v10.6をサポートする必要がない場合)、保持サイクルを中断するために__block値をnilに設定することです。

アップルのドキュメント



0

ブロックでselfを使用する場合は、selfを保持する可能性があるため、__ blockではなく__weakを使用する必要があります。

強い自己が必要な場合は、次のように使用できます。

__weak typeof(self) *weakSelf = self;
[self methodThatTakesABlock:^{
    if (weakSelf) {
        __strong typeof(self) *strongSelf = weakSelf;
        [strongSelf doSomething];
    }
}];
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.