- キー・バリュー・コーディング-
なぜキー・バリュー・コーディングを使うのか?
キー・バリュー・コーディングは、アクセッサメソッドの呼び出しやインスタンス変数を使う代わりに、プロパティを識別する文字列を使って、オブジェクトのプロパティに非直接的にアクセスするメカニズムです。
キー・バリュー・コーディングは、スクリプト可能なアプリケーションを作るときに、重要なテクニックになります。また、コントローラレイヤを使ったバインディングの、中心的な技術でもあります。キー・バリュー・コーディングのメソッドは、多くの場合、アプリケーションのコードをシンプルにすることにも利用することができます。
キー・バリュー・コーディングの主要なメソッドは、Objective-C のインフォーマルプロトコルである NSKeyValueCoding で宣言されていて、そのデフォルトの実装は NSObject が提供しています。オブジェクトの値を取得するためのメソッドは、valueForKey: です。このメソッドは、指定したキーで識別されるプロパティの値を返します。setValue:forKey: メソッドは、指定したキーで識別されるプロパティの値を設定します。
キー・バリュー・コーディングは、オブジェクトのプロパティも、NSNumber や NSValue でサポートされるスカラー値のデータ型や構造体も、同じようにサポートします。オブジェクトではないパラメタや返り値型は、必要に応じて、自動的にラッパーが提供されます。
setValue:forKey: と valueForKey: のデフォルトの実装は、まず指定したキーのアクセッサメソッドを利用しようとします。アクセッサが存在しない場合は、インスタンス変数が直接アクセスされます。この検索の実装の詳細は、「アクセッサ検索の実装の詳細」で説明されます。
目次
キー・バリュー・コーディングとスクリプティング
コードをシンプルにするために、キー・バリュー・コーディングを使う
NSNamedValueSequence クラス
キー・バリュー・コーディングとスクリプティング
Cocoa でのスクリプティングのサポートは、アプリケーションのモデルオブジェクトを通して、簡単に実装できるようにデザインされています。ユーザがアプリケーションで AppleScript コマンドを実行する場合、そのゴールはそのコマンドを実行させるために、アプリケーションのモデルオブジェクトに直接コマンドを渡すことです。
Mac OS X のスクリプティングは、AppleScript コマンドの実行を自動的にサポートするために、キー・バリュー・コーディングに強く依存しています。スクリプト可能なアプリケーションでは、モデルオブジェクトはサポートするキーのセットを定義します。それぞれのキーは、モデルオブジェクトのプロパティを表します。スクリプティングのキーの例としては、words、font、documents、color などがあります。キー・バリュー・コーディングの API は、キーの値を表すオブジェクトを問い合わせたり、キーに新しい値を設定するための、汎用的で自動的な手段を提供します。
アプリケーションのオブジェクトをデザインしたように、モデルオブジェクトのキーのセットを定義して、それに対応するアクセッサメソッドを実装するべきです。すると、アプリケーションのスクリプト・スィートを定義するときに、そのキーをスクリプト可能なクラスがサポートするキーとして指定することができます。アプリケーションでキー・バリュー・コーディングをサポートしていれば、何もしなくても、スクリプティング・サポートの恩恵を受けることができます。
AppleScript では、オブジェクトの階層は、アプリケーションのモデルオブジェクトの構造を定義します。多くの AppleScript コマンドは、このオブジェクトの階層が親コンテナから子の要素まで貫くことで、1 つかそれ以上のオブジェクトを指定します。また、クラスを表記するキー・バリュー・コーディングを使うことで、プロパティ間の関連を定義できます。詳しくは、「オブジェクトの関連を表記する」を参照してください。
Cocoa のスクリプティングのサポートは、スクリプト可能なオブジェクトで情報を取得、設定する際に、キー・バリュー・コーディングを利用します。Objective-C のインフォーマルプロトコルである NSScriptKeyValueCoding と、Java のインタフェースである NSScriptingKeyValueCoding が、キー・バリュー・コーディングと共に動くための機能を追加します。これには、マルチバリュー・キーでインデックスを指定してキーの値を取得、設定するものや、キーの値を適切なデータ型へ強制する(または変換する)ものが含まれます。
コードをシンプルにするために、キー・バリュー・コーディングを使う
キー・バリュー・コーディングのメソッドを、自分で書いたコードの実装を一般化するために使うこともできます。たとえば、NSTableView と NSOutlineView オブジェクトは、それぞれの列に文字列の識別子を関連づけています。この識別子を、表示させたいプロパティのキーと同じにすることで、コードを劇的に単純化することができます。
リスト 1-1 は、NSTableView のデリゲートメソッドの実装を、キー・バリュー・コーディングを使わないで行ったものです。リスト 1-2 は、キー・バリュー・コーディングを利用した実装です。キーとして列の識別子を使い、適切なオブジェクトを返しています。
リスト 1-1 キー・バリュー・コーディングを使わないデータソースメソッドの実装
- (id)tableView:(NSTableView *)tableview
objectValueForTableColumn:(id)column
row:(int)row
{
ChildObject *child = [childrenArray objectAtIndex:row];
if ( [[column identifier] isEqualToString:@"name"] ) {
return [emp name];
}
if ( [[column identifier] isEqualToString:@"age"] ) {
return [emp age];
}
if ( [[column identifier] isEqualToString:@"favoriteColor"] ) {
// etc...
}
// etc...
}
リスト 1-2 キー・バリュー・コーディングを使ったデータソースメソッドの実装
- (id)tableView:(NSTableView *)tableview
objectValueForTableColumn:(id)column
row:(int)row
{
ChildObject *child = [childrenArray objectAtIndex:row];
return [child valueForKey:[column identifier]];
}
NSNamedValueSequence クラス
キー・バリュー・コーディングに加えて、Cocoa は NSNamedValueSequence という Java のクラスを提供しています。このクラスは、キーのセットを定義し、スカラー値とオブジェクトの値をそれに設定することを可能にします。このクラスはNSMutableDictionary と似ていますが、NSNamedValueSequence は固定要素数で作られて、getFloatWithName や setFloatWithName のような便利なメソッドを定義しています。もし定義されていないキーを問い合わせると、デフォルトである 0 か nil が返されます。オブジェクトの数がキーの容量を超えた後、さらにキーを追加しようとすると失敗します。NSNamedValueSequence のサイズを変更することはできませんし、キーを削除することもできません。