2013-07-24 15 views
6

ブロックの更新を確認するためにスカラー変数に__blockストレージタイプが必要ですが、オブジェクトにはいつ必要なのですか?私は__weakは、ブロック内で使用される自己参照をキャプチャするときに使用する必要があると信じていますが、通常のオブジェクトには実際にストレージタイプを使用する必要があるときは表示されません。ARCでオブジェクト参照に__blockキーワードを使用する場合

+0

[何__weakと__blockの違い参照?](http://stackoverflow.com/questions/11773342/what-the-difference-between-weak-and-block-reference) –

+0

私は特に尋ねています: '__block'ストレージタイプsh ARCを使用するときにスカラーではないオブジェクト参照で使用されますか?それらの他のリンクがその質問に答えるなら私はそれを逃した。 – chinabuffet

+0

@chinabuffet:スカラー型とオブジェクトポインタ型の違いはありません。 – newacct

答えて

15

__blockは、スカラー変数の値をブロック内のコードで変更したい場合に必要です。キャプチャされたスカラーはブロック内にconstと表示されるため、変更することはできません。オブジェクトへのポインタがある場合、同じ区別が適用されます。キャプチャされたポインタ自体はポインタconstになります。したがって、変更することはできませんが、オブジェクト内のオブジェクトはブロック内のコードによって変更できます。指示されたオブジェクトを変更する場合は、ポインタ自体を変更する必要があるため、ポインタは__blockタイプで宣言する必要があります。オブジェクト自体を__blockと宣言する必要はありませんが、ポインタを変更する必要がある場合に限り、オブジェクトへのポインタだけを宣言する必要はありません。

あなたが正しいメンタルモデルを持っていれば、ブロックは紛らわしいことではありません。ブロックはスタックに最初に割り当てられていることを知っておくことが重要です。スタックフレームがポップされるとレキシカルスコープが破棄されると消滅します。ブロックが作成されたレキシカルスコープのライフタイムを過ぎてブロックがハングするようにするには、Block_copy()を使用してヒープに移動するか、-copyというメッセージを送信します。ブロックがヒープにコピーされると、キャプチャされたすべてのconst変数が移動し、変数constが指すオブジェクトがすべて保持されます。ブロックがヒープから削除されると、const変数が指すすべてのオブジェクトが解放されます。

__block変数 "under the hood"には、ブロックに含まれるコンパイラが使用する(そして表示されない)間接的なインダイレクション層があるため、ブロックがヒープにコピーされると、キャプチャされた__block変数不可視ポインタは、これらの__block変数の新しいヒープ位置を指すように調整されます。つまり、変数__blockのアドレスが変更される可能性があるため、そのアドレスを使用する場合は注意が必要です。 __block変数は、ある意味ではブロックの外側に存在することがわかります。したがって、これらの変数はブロック外部のコードから読み取って変更できます。

私は簡単にしてきたが、あなたはますます複雑に記載されている、ここではより良い説明を見つけることができます。また

http://ios-blog.co.uk/tutorials/programming-with-blocks-an-overview/

http://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html

http://www.mikeash.com/pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html

+0

ブロックが参照としてどこかに渡された場合、そのブロックをパラメータとして受け取っているものは、ブロックをすぐにコピーして将来使用する必要がありますか? – chinabuffet

+0

ブロック参照が、ブロックが定義されているレキシカルスコープ(スタックフレーム)よりも長時間続く場合は、ブロックオブジェクトをヒープに移動するためにブロック参照をコピーする必要があります。私はブロックを作成するときにコピーを作成する方が、作成から離れた場所でこれらのコピーを作成するよりも安全だと思います。 – Fred

0

これらは、関数レベルの変数に使用されます。これらはブロック(および囲みスコープ)内で変更可能であり、参照するブロックがヒープにコピーされると保持されます。 __block記憶修飾子で宣言された囲むレキシカルスコープのローカル変数は、参照によって提供されるため、変更可能です。すべての変更は、同じ囲みレキシカルスコープ内で定義された他のブロックを含む、囲みレキシカルスコープに反映されます。

__block変数は、変数のレキシカルスコープと、変数のレキシカルスコープ内で宣言または作成されたすべてのブロックおよびブロックコピーとの間で共有されるストレージに存在します。したがって、フレーム内で宣言されたブロックのコピーがフレームの終わりを超えても存続する場合(たとえば、後で実行するためにキューに入れられるなど)、ストレージはスタックフレームの破棄に耐えられます。したがって、ブロック内のオブジェクトを変更する必要がある場合や、スタックフレームが破棄された後にオブジェクトが必要な場合に使用してください。

関連する問題