7

現在、Obj-Cブロックの基本と__blockストレージタイプを理解するのに問題があります。次のドキュメントから:

http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW6

私は次の段落と例を理解しようとしています:

ブロックがコピーされると、ブロック内で使用されるオブジェクト変数への強力な参照が作成されます。メソッドの実装内でブロックを使用する場合:

参照によってインスタンス変数にアクセスする場合、自己への強力な参照が行われます。値でインスタンス変数にアクセスする場合、変数への強力な参照が行われます。次の例は、2つの異なる状況を示しています。

dispatch_async(queue, ^{
    // instanceVariable is used by reference, a strong reference is made to self
    doSomethingWithObject(instanceVariable);
});

id localVariable = instanceVariable;
dispatch_async(queue, ^{
    /*
      localVariable is used by value, a strong reference is made to localVariable
      (and not to self).
    */
    doSomethingWithObject(localVariable);
});

特定のオブジェクト変数のこの動作をオーバーライドするには、__blockストレージタイプ修飾子を使用してマークを付けることができます。

私の質問:

  1. 一方の例は「参照によってアクセス」され、もう一方の例は変数によってアクセスされるので、どの程度正確ですか。localVariableが「値によって使用される」のはなぜですか?
  2. このドキュメントは、「自己を強く参照する」とはどういう意味ですか?それはどの「自己」を指しているのですか?
  3. 2番目の例で__blockストレージタイプをlocalVariableに追加した場合、ブロックが変数を閉じて、ブロックが解放されるまでヒープ内に保持されると想定するのは間違っていますか?他に何が起こっていますか?

ありがとうございました!

4

1 に答える 1

6

1つの例は「参照によってアクセス」され、他の例は変数によってアクセスされますか? localVariable が「値によって使用される」のはなぜですか?

これを理解する 1 つの方法は次のとおりです。

  1. メソッドで定義されたブロックでローカル変数を使用すると、ブロックの実行時 (メソッドの終了後) に変数の内容が使用できるように、変数の内容がブロックのプライベート メモリにコピーされます。この意味で、「値による」アクセスについて話すことができます (例: 値はコピーされます)。構文的には、コンパイラは の内容が何を参照しているのかわからないlocalVariableため、その値はそのように扱われます。

  2. クラスのメソッド内で定義されたブロックに直接アクセスする場合instanceVariable、コンパイラは、メソッドを実行している同じオブジェクトにアクセスしていることを認識し、何もコピーする必要はありません。ブロックが見つかりました。ただし、ブロックが実行されたときにオブジェクトがまだそこにあることを確認する必要があるため、オブジェクトへの強い参照を取得します。

ここで、「参照による」の使用について: 最初のケースでは、クラス メンバへの参照のコピーを取得します: その値を変更できる場合 (ただし、コンパイラが禁止しているため変更できません)、ブロックのプライベート コピーを変更しただけなので、元のオブジェクトは影響を受けません。

2 番目のケースでは、の値を変更できますinstanceVariable(例: それをnil介して参照されるオブジェクトを割り当てます)。これは、ブロックが定義されている場合にメソッドを実行したオブジェクトに影響します。

「自己への強い参照が行われている」というドキュメントの意味は何ですか? それはどの「自分」を指していますか?

selfブロックが見つかったメソッドを現在実行しているオブジェクトです。強い参照が行われるということは、(ARC の用語で) オブジェクトの保持カウントがインクリメントされることを意味するだけです (他のエンティティがオブジェクトを解放して割り当てを解除できないようにするため)。

2 番目の例で __block ストレージ タイプを localVariable に追加すると、ブロックが変数を閉じて、ブロックが解放されるまでヒープ内に保持されると仮定するのは間違っていますか? 他にどのようなことが起こっていますか?

を使用__blockすると、変数は常に「参照によって」アクセスされるため、変数を変更できます。

これらは次のように処理されます。

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

最適化として、ブロック ストレージはブロック自体と同じようにスタックから開始します。ブロックが Block_copy を使用して (またはブロックがコピーを送信された場合は Objective-C で) コピーされる場合、変数はヒープにコピーされます。したがって、__block 変数のアドレスは時間の経過とともに変化する可能性があります。

于 2013-01-22T17:25:59.890 に答える