「Blocks and Variables」の編集履歴(バックアップ)一覧はこちら
「Blocks and Variables」(2010/05/12 (水) 18:15:35) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
//0.下はいじらない
Tags:&tags()
//1.以下に続けてADCでの分類を書き込みリンクする。「ガイド小見出し(日本語名)」、まで書く
&link_toppage(トップ) > [[ガイド>Guides]] > ブロックプログラミング概論
//前後のページへのリンクをはる。ページ最下部にも同じものがあるので忘れずにリンクする
[[前のページ>]] [[次のページ>]]
*ブロックと変数 [[翻訳元>http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW1]]
この記事ではブロックと変数間の内部的な働きをメモリ管理も含めて説明します。
//3.翻訳元の最終更新日を書く
このページの最終更新:&date()
ADCの最終更新:2009-10-19
//目次は自動生成
目次
#contents(fromhere=true)
//4.以下、用語は頻繁に出てくる単語の翻訳ガイドラインを参照しながら翻訳する。
//5.ある程度書き終わったらタグ(未完または完成、カテゴリ名×3)をつけて下線を引く(広告との境)。これで終了。それではGood Luck!
**変数の型(Types of Variable)
----
ブロックオブジェクトのコードの集合では、変数は五つの異なる形で扱われます。
三つの標準的な変数の型は関数内と全く同様に参照することができます。
- グローバル変数。静的変数を含む。
- グローバル関数(厳密には変数ではない)。
- スコープに囲まれたローカル変数とパラメータ。
またブロックは他に二つの変数の型をサポートしています。
+ [At function level are __block variables.]これらはブロック(とスコープ)内で変更可能で、参照されているどんなブロックがヒープにコピーされても保護されます。
+ constの取り込み
最後に、メソッドの実装中ではブロックはObjective-Cインスタンス変数を参照できます。「オブジェクトとブロック変数(Object and Block Variables)」を参照してください。
ブロック中で使用される変数には以下の規則が適用されます。
+ グローバル変数とレキシカルスコープ中に存在する静的変数はアクセス可能です。
+ ブロックに渡されたパラメータ(ちょうど関数の引数のように)はアクセス可能です。
+ レキシカルスコープに囲まれた局所的なスタック(静的でない)変数はconst変数として切り取られます。&br()この変数はプログラム中でブロック表現にさしかかった時に取得されます。ネストされたブロックでは、この値は最も近いスコープから切り取られます。
+ レキシカルスコープ中で__blockストレージ型修飾子で宣言された変数は参照で提供されるので変更可能になります。&br()そのレキシカルスコープ中での変更は同じスコープで宣言された他のブロックのも含め全て反映されます。これらは「__block ストレージ型(The __block Storage Type)」で詳説しています。
+ ブロック中のレキシカルスコープ中で宣言されたローカル変数は関数中のローカル変数と全く同じように働きます。&br()ブロックの呼び出しではそれぞれこの変数の新しいコピーが作られます。これらの変数はブロック中のブロックでconstや参照変数として代わる代わる使うことができます。
以下の例では静的でないローカル変数の用法を説明しています。
|BGCOLOR(#eff):int x = 123;&br() &br()void (^printXAndY)(int) = ^(int y) {&br() &br() printf("%d %d\n", x, y);&br()};&br() &br()printXAndY(456); // prints: 123 456|
注意してほしいのは、ブロック中でxで新しい値を参照しようとするとエラーになることです。
|BGCOLOR(#eff):int x = 123;&br() &br()void (^printXAndY)(int) = ^(int y) {&br() &br() x = x + y; // error&br() printf("%d %d\n", x, y);&br()};|
変数をブロック中で変更できるようにするには、__blockストレージ型修飾子を使用します。「__block ストレージ型(The __block Storage Type)」をご覧ください。
**__block ストレージ型(The __block Storage Type)
----
__block型修飾子を適用することによって読み込んだ変数を変更可能であること、つまり読み書き可能であることを明示できます。__blockストレージ型はローカル変数を修飾するregister、auto、staticストレージ型と似ていますが、同時に使うことはできません。
__block変数はその変数のレキシカルスコープと、その中で生成または宣言された全てのブロックとその複製で共有されるストレージに確保されます。したがって、スタックフレームが破棄されても(例えば後で実行する為にどこかに待機させることで)、その中で宣言されたブロックの複製が生存していれば、ストレージは決して破棄されません。一つのレキシカルスコープ中の複数のブロックは共有する変数を同時に使うことがあります。
最適化の為に、ブロックストレージはブロック自体と同じようにまずスタック外に確保されます。もしブロックがBlock_copyを使って(またはObjective-Cでブロックにcopyを送って)コピーされれば、変数はヒープにコピーされます。つまり、&bold(){__block変数のアドレスは時間とともに変わることがあります。}
__block変数にはもう二つの制限があり、可変長の配列がなること、C99可変長配列を含む構造体がなることはできません。
以下の例では__block変数の用法を説明しています。
|__block int x = 123; // xはブロックストレージ中に確保される&br() &br()void (^printXAndY)(int) = ^(int y) {&br() &br() x = x + y;&br() printf("%d %d\n", x, y);&br()};&br()printXAndY(456); // prints: 579 456&br()// 今xは579|
以下の例ではいくつかの異なる型の変数とブロック間の相互作用を示しています。
|extern NSInteger CounterGlobal;&br()static NSInteger CounterStatic;&br() &br();{&br() NSInteger localCounter = 42;&br() __block char localCharacter;&br() &br() void (^aBlock)(void) = ^(void) {&br() ++CounterGlobal;&br() ++CounterStatic;&br() CounterGlobal = localCounter; // localCounter fixed at block creation&br() localCharacter = 'a'; // sets localCharacter in enclosing scope&br() };&br() &br() ++localCounter; // unseen by the block&br() localCharacter = 'b';&br() &br() aBlock(); // execute the block&br() // localCharacter now 'a'&br()}|
**オブジェクトとブロック変数
----
ブロックはObjective-CとC++のオブジェクトや別ブロックへのサポートを変数という形で提供しています。
*Objecive-Cオブジェクト
リファレンスカウンタ環境下では、ブロック中でObjective-Cオブジェクトを参照するときには通常そのオブジェクトを保持します。これはオブジェクトのインスタンス変数を単純に参照する場合でも当てはまります。ですが、__blockストレージ型修飾子のついたオブジェクト変数は保持されません。
|&bold(){注:}ガベージコレクタ環境下では、__weak修飾子や__block修飾子を変数に適用した場合、そのブロックではその変数が確保されていることを保証できません。|
ブロックをメソッドの実装内で使用した場合、オブジェクトインスタンス変数のメモリ管理の規則はさらに巧妙になります。
- インスタンス変数に参照渡しでアクセスしている場合には、selfが保持されます。
- インスタンス変数に値渡しでアクセスしている場合には、その変数が保持されます。
以下の例ではこの異なる二つの状況を説明しています。
|dispatch_async(queue, ^{&br()&br() // instanceVariableは参照を使用しているのでselfが保持されます&br()&br() doSomethingWithObject(instanceVariable);&br()&br()});&br()&br() &br()&br() &br()&br()id localVariable = instanceVariable;&br()&br()dispatch_async(queue, ^{&br()&br() // localVariableは値を使用しているので、localVariableが保持されます(selfではありません)&br()&br()&br() doSomethingWithObject(localVariable);&br()&br()});|
#right(){[[前のページ>Getting Started with Blocks]] [[次のページ>]]}
----
//0.下はいじらない
Tags:&tags()
//1.以下に続けてADCでの分類を書き込みリンクする。「ガイド小見出し(日本語名)」、まで書く
&link_toppage(トップ) > [[ガイド>Guides]] > ブロックプログラミング概論
//前後のページへのリンクをはる。ページ最下部にも同じものがあるので忘れずにリンクする
[[前のページ>]] [[次のページ>]]
*ブロックと変数 [[翻訳元>http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW1]]
この記事ではブロックと変数間の内部的な働きをメモリ管理も含めて説明します。
//3.翻訳元の最終更新日を書く
このページの最終更新:&date()
ADCの最終更新:2009-10-19
//目次は自動生成
目次
#contents(fromhere=true)
//4.以下、用語は頻繁に出てくる単語の翻訳ガイドラインを参照しながら翻訳する。
//5.ある程度書き終わったらタグ(未完または完成、カテゴリ名×3)をつけて下線を引く(広告との境)。これで終了。それではGood Luck!
**変数の型(Types of Variable)
----
ブロックオブジェクトのコードの集合では、変数は五つの異なる形で扱われます。
三つの標準的な変数の型は関数内と全く同様に参照することができます。
- グローバル変数。静的変数を含む。
- グローバル関数(厳密には変数ではない)。
- スコープに囲まれたローカル変数とパラメータ。
またブロックは他に二つの変数の型をサポートしています。
+ [At function level are __block variables.]これらはブロック(とスコープ)内で変更可能で、参照されているどんなブロックがヒープにコピーされても保護されます。
+ constの取り込み
最後に、メソッドの実装中ではブロックはObjective-Cインスタンス変数を参照できます。「オブジェクトとブロック変数(Object and Block Variables)」を参照してください。
ブロック中で使用される変数には以下の規則が適用されます。
+ グローバル変数とレキシカルスコープ中に存在する静的変数はアクセス可能です。
+ ブロックに渡されたパラメータ(ちょうど関数の引数のように)はアクセス可能です。
+ レキシカルスコープに囲まれた局所的なスタック(静的でない)変数はconst変数として切り取られます。&br()この変数はプログラム中でブロック表現にさしかかった時に取得されます。ネストされたブロックでは、この値は最も近いスコープから切り取られます。
+ レキシカルスコープ中で__blockストレージ型修飾子で宣言された変数は参照で提供されるので変更可能になります。&br()そのレキシカルスコープ中での変更は同じスコープで宣言された他のブロックのも含め全て反映されます。これらは「__block ストレージ型(The __block Storage Type)」で詳説しています。
+ ブロック中のレキシカルスコープ中で宣言されたローカル変数は関数中のローカル変数と全く同じように働きます。&br()ブロックの呼び出しではそれぞれこの変数の新しいコピーが作られます。これらの変数はブロック中のブロックでconstや参照変数として代わる代わる使うことができます。
以下の例では静的でないローカル変数の用法を説明しています。
|BGCOLOR(#eff):int x = 123;&br() &br()void (^printXAndY)(int) = ^(int y) {&br() &br() printf("%d %d\n", x, y);&br()};&br() &br()printXAndY(456); // prints: 123 456|
注意してほしいのは、ブロック中でxで新しい値を参照しようとするとエラーになることです。
|BGCOLOR(#eff):int x = 123;&br() &br()void (^printXAndY)(int) = ^(int y) {&br() &br() x = x + y; // error&br() printf("%d %d\n", x, y);&br()};|
変数をブロック中で変更できるようにするには、__blockストレージ型修飾子を使用します。「__block ストレージ型(The __block Storage Type)」をご覧ください。
**__block ストレージ型(The __block Storage Type)
----
__block型修飾子を適用することによって読み込んだ変数を変更可能であること、つまり読み書き可能であることを明示できます。__blockストレージ型はローカル変数を修飾するregister、auto、staticストレージ型と似ていますが、同時に使うことはできません。
__block変数はその変数のレキシカルスコープと、その中で生成または宣言された全てのブロックとその複製で共有されるストレージに確保されます。したがって、スタックフレームが破棄されても(例えば後で実行する為にどこかに待機させることで)、その中で宣言されたブロックの複製が生存していれば、ストレージは決して破棄されません。一つのレキシカルスコープ中の複数のブロックは共有する変数を同時に使うことがあります。
最適化の為に、ブロックストレージはブロック自体と同じようにまずスタック外に確保されます。もしブロックがBlock_copyを使って(またはObjective-Cでブロックにcopyを送って)コピーされれば、変数はヒープにコピーされます。つまり、&bold(){__block変数のアドレスは時間とともに変わることがあります。}
__block変数にはもう二つの制限があり、可変長の配列がなること、C99可変長配列を含む構造体がなることはできません。
以下の例では__block変数の用法を説明しています。
|__block int x = 123; // xはブロックストレージ中に確保される&br() &br()void (^printXAndY)(int) = ^(int y) {&br() &br() x = x + y;&br() printf("%d %d\n", x, y);&br()};&br()printXAndY(456); // prints: 579 456&br()// 今xは579|
以下の例ではいくつかの異なる型の変数とブロック間の相互作用を示しています。
|extern NSInteger CounterGlobal;&br()static NSInteger CounterStatic;&br() &br();{&br() NSInteger localCounter = 42;&br() __block char localCharacter;&br() &br() void (^aBlock)(void) = ^(void) {&br() ++CounterGlobal;&br() ++CounterStatic;&br() CounterGlobal = localCounter; // localCounter fixed at block creation&br() localCharacter = 'a'; // sets localCharacter in enclosing scope&br() };&br() &br() ++localCounter; // unseen by the block&br() localCharacter = 'b';&br() &br() aBlock(); // execute the block&br() // localCharacter now 'a'&br()}|
**オブジェクトとブロック変数
----
ブロックはObjective-CとC++のオブジェクトや別ブロックへのサポートを変数という形で提供しています。
*Objecive-Cオブジェクト
リファレンスカウンタ環境下では、ブロック中でObjective-Cオブジェクトを参照するときには通常そのオブジェクトを保持します。これはオブジェクトのインスタンス変数を単純に参照する場合でも当てはまります。ですが、__blockストレージ型修飾子のついたオブジェクト変数は保持されません。
|&bold(){注:}ガベージコレクタ環境下では、__weak修飾子や__block修飾子を変数に適用した場合、そのブロックではその変数が確保されていることを保証できません。|
ブロックをメソッドの実装内で使用した場合、オブジェクトインスタンス変数のメモリ管理の規則はさらに巧妙になります。
- インスタンス変数に参照でアクセスしている場合には、selfが保持されます。
- インスタンス変数に値でアクセスしている場合には、その変数が保持されます。
以下の例ではこの異なる二つの状況を説明しています。
|dispatch_async(queue, ^{&br()&br() // instanceVariableは参照なのでselfが保持されます&br()&br() doSomethingWithObject(instanceVariable);&br()&br()});&br()&br() &br()&br() &br()&br()id localVariable = instanceVariable;&br()&br()dispatch_async(queue, ^{&br()&br() // localVariableは値なので、localVariableが保持されます(selfではありません)&br()&br()&br() doSomethingWithObject(localVariable);&br()&br()});|
#right(){[[前のページ>Getting Started with Blocks]] [[次のページ>]]}
----
表示オプション
横に並べて表示:
変化行の前後のみ表示: