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;

ここでもまったく同じですか?</ p>

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

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

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

4

4 に答える 4

109

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

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

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

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

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

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

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

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

于 2012-08-02T08:19:24.757 に答える
5

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

アップルドキュメント

于 2013-07-31T08:32:48.213 に答える
0

__blockvsに関する他の回答に加え__weakて、シナリオで保持サイクルを回避する別の方法があります。

@weakify(self);
[self methodThatTakesABlock:^ {
    @strongify(self);
    [self doSomething];
}];

@Weakify@Strongifyマクロに関する詳細情報

于 2018-01-26T08:58:22.800 に答える
0

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

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

__weak typeof(self) *weakSelf = self;
[self methodThatTakesABlock:^{
    if (weakSelf) {
        __strong typeof(self) *strongSelf = weakSelf;
        [strongSelf doSomething];
    }
}];
于 2019-05-01T22:44:29.663 に答える