- Cocoa バインディング-
Master-Detail インタフェースの作成
この記事は、簡単な Master-Detail インタフェースを実装するために、どのようにバインディングを使うかを説明します。Master インタフェースでは、オブジェクトの集合を表示するために、テーブルビューが使われます。Detail インタフェースでは、選択されたオブジェクトを表示するために、その他いろいろなビューが使われます。この記事は、テーブルの列を配列コントローラにバインディングする例を含みます。
Master-Detail インタフェースは、この記事でカバーされている以外の方法でも、さまざまな方法で拡張できます。特に、テーブルビューには、Cocoa バインディングとシームレスに動作する、さまざまな特性があります。それらについては、次の記事を参照してください。
目次:
Master-Detail インタフェースとは何か?
モデルの作成
ビューの作成
コントローラの作成
コントローラからモデルへのバインディング
ビューからコントローラへのバインディング
Master-Detail インタフェースとは何か?
Master-Detail インタフェース では、ユーザはオブジェクトのリストからオブジェクトを選んで、その選択したオブジェクトを詳しく見ることができます。Master インタフェース はオブジェクトの集合を表示し、Detail インタフェース は選択されたオブジェクトのインスペクタを実装します。ユーザが Master インタフェースでの選択を変更すれば、Detail インタフェースは更新されて、新しく選択されたオブジェクトを表示します。どのオブジェクトも選択されていないときは、Detail インタフェースは何も表示しないか、使用不可になります(もし編集可能なら)。複数のオブジェクトが選択されているときは(複数選択が可能だとしたら)、Detail インタフェースは使用不可になるか、すべての選択されたオブジェクトを表示します。通常、このようなインタフェースでは、ユーザが集合にオブジェクトを追加したり、削除したりすることができます。
Master-Detail インタフェースを、どのコンポーネントを使って実装するかは、アプリケーションによります。Master イタフェースがテーブルビューで実装され、Detail インタフェースがいくつかのビューの組み合わせで実装されて、Master インタフェースの上か下かにある、というケースがよくあります。図 1 は、メディア管理アプリケーションでの Master-Detail インタフェースです。この例では、テーブルビューはメディアオブジェクトの集合を表示して、その下にあるビューは選択されたメディアオブジェクトのプロパティを表示します。
Master-Detail インタフェース

モデルの作成
この記事では、すでにモデルのデザインは終わっているものとします。モデルとは、アプリケーションのデータをカプセル化して、そのデータを操作するメソッドを提供するオブジェクトです。Master-Detail インタフェースは、モデルオブジェクトの集合を表示するために使われます。ですから、作成したモデルオブジェクトのルートは、これらのオブジェクトの集合であるとよいでしょう。
たとえば、図 2 はメディア管理アプリケーションのモデルのオブジェクト図を表しています。この例では、アプリケーションはドキュメント・ベース・アプリケーションを使い、MyDocument(MyDocument.nib の File's Owner)は Media オブジェクトの配列として初期化される、mediaAssets オブジェクトを持ちます。
オブジェクトモデル

ビューの作成
図 1 の Master インタフェースはテーブルビューを使っていて、それぞれの列は表示されているオブジェクトのプロパティと対応しています。テーブルビューが、タイトルや日付といった属性と同様に、著作者のような関連も表示していることに注意してください。著作者プロパティは対一関連(図 2 を参照)で、Person オブジェクトに対応しています。対一関連は、様々な方法で表示することができます。たとえば、Mster インタフェースは名字だけを表示しています。Detail インタフェースでは、ポップアップメニューから著作者を選ぶことができます。
Interface Builder を使って、図 1 と同じように Master-Detail インタフェースをレイアウトしてください。この例では、メディアの画像を表示するために、画像セルが Image の列に設定されています。また、日付のためのフォーマッタが Date の列に設定されています。Author の列は、著作者の名字を表示していますが、ポップアップメニューのセル、NSPopUpButtonCell、を設定して、メニューとして表示することもできます。
コントローラの作成
次に、ビューをコントローラ経由でモデルにつなぐ必要があります。NSArrayController は、選択可能なオブジェクトの集合を管理するためにデザインされています。これは Master-Detail インタフェースの実装にぴったりです。配列コントローラを作ったら、そのコンテントをモデルオブジェクトの集合に設定します。配列コントローラが編集可能ならば、モデルのインスタンスを作って、集合に加えることもできます。これを動作させるためには、配列コントローラに管理するクラスの名前を教える必要があります。
Master-Detail インタフェースで配列を作成、設定するには、次のようにしてください。
- Interface Builder で NSArrayController をドラッグして、配列コントローラを作ってください。
- 図 3 のように、Info ウィンドウの Attributes ペインで、Object Class Name フィールドにモデルのクラス名を入れてください。
- ユーザにモデルを編集してほしくない場合は、Attributes ペインの Editable チェックボックスを外してください。それか、コレクションに追加か削除してください。
配列コントローラの Attributes ペイン

コントローラからモデルへのバインディング
ビューとコントローラは、それぞれバインディングを公開しています。Interface Builder を使って、Info ウィンドウの Bindings ペインを表示することで、バインディングを詳しく見ることができます。nib ファイルの配列コントローラを選択して、バインディングを表示したものが、図 4 です。
配列コントローラのコンテントは、contentArray バインディングを設定することで指定できます。たとえば、File's Owner が mediaAssets という Media オブジェクトの集合を管理しているとすると、contentArray の設定は次のようになります。
-
Bind to 特性に、モデルオブジェクトの集合を管理しているオブジェクト(この例では File's Owner)を設定する。
-
Controller Key を空白にする。
-
Model Key Path に、配列の名前(この例では mediaAssets)を設定する。
図 4 は、contentArray バインディングがどのようになっているべきかを示しています。
配列コントローラの Bindings ペイン

これで、このコントローラは、Media オブジェクトの集合と、その配列への Media オブジェクトの追加と削除を管理するように設定されました。このコントローラのデフォルトの動作を変更した場合は、Attributes ペインに戻ってください。ユーザに集合を編集してほしくないときは、Editable チェックボックスを外します。
ビューからコントローラへのバインディング
次に、ビューオブジェクトのバインディングを設定して、ビューを配列コントローラにつなぎます。Master と Detail インタフェースそれぞれのビューを、配列コントローラに結びつけます。
このバインディングには複雑なものもあります。たとえば、編集可能な対一関連などです。この記事は、基本的なバインディングだけを扱います。もっと複雑なバインディングの例は、「バインディングを使った画像の表示」や「ポップアップメニューを使って対一関連を実装する」を参照してください。
一般的には、コンテントを表示するビューは、value と呼ばれるバインディングを持つか、value という単語を持つバインディングを含むことを、思い出してください。
また、ビューをコントローラに結びつけるので、コントローラのプロパティに詳しくなくてはいけません。配列コントローラはいくつか主要なプロパティを持っており、これらは Controller Key 特性の値として使われます。
-
arrangedObjects—表示されているオブジェクトの集合を示します。
-
selection—arrangedObjects のうち、選択されているオブジェクトを示します。
-
selectedObjects—arrangedObjects のうち、複数の選択されているオブジェクトを示します。
Master インタフェースのバインディング
Master インタフェースでは、実はテーブルビューのバインディングではなくて、テーブルの列のバインディングを設定します。テーブルの列で特別のタイプのセルを使っていたとしても、たとえば画像セルや NSPopUpButtonCell、セルではなくてテーブルの列を設定します。NSTableColumn へのバインディングは、セルによって変化するでしょう。
この例では、テーブルビューのそれぞれの行は 1 つの Media オブジェクトに対応し、それぞれの列は Media オブジェクトのプロパティを表示する必要があります。プロパティを表示するには、まずテーブルビューで列を選択して、Bindings ペインを表示し、value バインディングを開きます。そして、列を arrangedObjects キーに結びつけます。なぜなら、1 つのセルだけではなくて、列全体のコンテントを設定するからです。それぞれの value を、Media オブジェクトのプロパティを表示するために、次のように設定します。
-
Bind to 特性に、コントローラオブジェクトを設定します。たとえば、MediaAssetsController になります。
-
Controller Keyに、arrangedObjects(表示されているオブジェクトの集合)を設定します。
-
Model Key Pathに、その列に表示したプロパティを設定します。たとえば、メディア管理アプリケーションでは、Data の列には date を設定します。
図 5 では、Bindings ペインでの、Title 列の value バインディングの様子を示しています。
NSTableColumn の Bindings ペイン

著作者プロパティの場合は、名字を表示するだけならば、Model Key Path に author.lastname を設定します。しかし、デフォルトのセルは編集可能なので、アプリケーションを動かすと、ユーザは Author 列を編集して、著作者の名字を変更することができます。もしこの動作をさせたくないならば、列を選択して、Info ウィンドウの Attributes ペインで Editable チェックボックスを外してください。
Cocoa のビューには、キー・バリュー・コーディングを使って、オブジェクトのリスをうまく表示できるものがすでにあることに注意してください。Controller Key と Model Key Path は、結びつけられているオブジェクトから値を取得するために、一緒にされています。テーブルの列の場合、Controller Key は配列を識別します。ですから、返ってくる値は配列です。たとえば、Author 列は名字の配列を取得するために、arrangedObjects.author.lastname キー・パスを使います。この配列は NSString のインスタンスの集合で、結びつけられたオブジェクトから取得されます。
Detail インタフェースのバインディング
Detail インタフェースでも、Master インタフェースと同様に、ビューを結びつけます。ただし、それぞれのバインディングの Controller Key に selection、現在選択されているオブジェクト、を設定するところが違います。
たとえば、図 1 にある、Detail インタフェースの Title テキストフィールドの value バインディングは、次のように設定します。
-
Bind to に、配列コントローラオブジェクトを設定します。この例では、MediaAssetsController です。
-
Controller Key に、selection(現在選択されているオブジェクト)を設定します。
-
Model Key Path に、ビューに表示したいプロパティを設定します。たとえば、title などです。