translation:adc:cocoa:foundation:cocoa_bindings:binding_your_preferences_in_cocoa

Cocoaにおける環境設定のバインド方法

原文 Binding Your Preferences in Cocoa http://developer.apple.com/cocoa/cocoabindings.html

Mac OS X v10.3 Pantherにおける刺激的な新技術の1つがCocoa Bindingです。 WebObjectEnterprise Objects frameworkで初導入された技術に由来し、この技術はアプリケーションの結合コード(glue code)の注目すべき後継者として歓迎されました。 多くのCocoa技術同様、Cocoa Bindingの働き方は巧妙で、あなたが「あー、なるほど」と感じ、起きている事を理解するには多少の訓練が必要です。 そう感じるようになるまでは、これらの騒々しい議論は何についての物なのだろう、と不思議に思うかも知れません。 しかし、一度“それ”を体験してしまうと、本技術なくしてはアプリケーションを作成したくなくなる事でしょう。

Cocoa Bindingを始める一番簡単な方法の1つは、アプリケーションの環境設定を管理する事です。 本記事は、ステップ・バイ・ステップ形式による環境設定の実装からグルーコードを取り除く作業通して、Cocoa Bindingの使い方を示します。 同時に、このステップ・バイ・ステップ形式が、あなたを「なるほど」の瞬間に導く事を望みます。

ユーザーが好みの環境に設定出来る事-アプリケーションの見た目や挙動を変更する事-は、どんなアプリケーションでも重要な事柄です。 以前は、それら環境設定の格納、復元方法は開発者任せでした。 有り難い事にCocoaはUser Defaultsシステムと呼ばれる、簡単かつ標準的なアプリケーションの環境設定を扱うための方法を提供しています。

極めて簡単に言えば、User Defaultシステムはキーと値の組みを格納し、後にその情報をキーによって復元する事を可能にします。 デフォルトシステムは、あなたのためにデータを格納し復元するという基本的な仕事の面倒を見ます。 これは、あなたが環境設定を保持するためのデータ形式を作る必要はない、ということを意味します。 また、環境設定は決まった場所に格納され、直接ないしdefaultsコマンドラインツール(defaultsコマンドは後で使います)を使って簡単に利用する事ができます。

環境設定システムはアプリケーション起動の合間に、様々な事柄を取り巻く関連データを巧みに解決し、アプリケーションの様々な部分が必要とする設定データにアクセス出来るようにします。 例えば、様々なユーザーインタフェースのテキスト要素の色と大きさを選べる、環境設定ウィンドウを作る事が出来ます。 一度環境設定ウィンドウを作ると、環境設定ウィンドウで変更のあった部分を環境設定システムに保存するためのコードを書く事が出来ます。 同様に、アプリケーションの様々なユーザーインタフェースには、環境設定システムからテキストの大きさと色を読み込むグルーコードによって、属性が設定されます。

ではここで時間を割いて、Model-View-Controllerという言葉-Cocoaの多くを形作る基本的なデザインパターン-について解説しましょう。 環境設定ウィンドウや色々なユーザーインタフェース要素のコンテナといった、アプリケーションの様々な視覚的要素がViewです。 環境設定システムはModelです。 Figure 1が示すように、ViewとModelの間にあるのがControllerです。 この真ん中にあるController層の中では、ユーザーインタフェースと環境設定システムを結びつける結合コードが必要です。


Figure 1: Model-View-Controllerの図式

前述の結合コードを書く事は、さほど複雑な仕事ではありません。 しかし面倒な問題が残っています。 例えばユーザーがアプリケーションの環境設定ウィンドウを使用し、環境設定が変わった際、その環境設定を利用するアプリケーションの様々な部分は、設定に変更があった事を自動では知る事が出来ません。 これは、アプリケーションの環境設定ウィンドウで設定したユーザー設定は、アプリケーションの実行中に自動的には有効にならず、次回起動時に有効になるという事を意味します。 この挙動(user experience)が平均点以下であることは、火を見るよりも明らかです。

結合コード使用の影響下にあるユーザーインタフェース部品を、即座に更新出来るようにする事は、なかなかの仕事になります。 環境設定ウィンドウが、何らかの形でユーザーインタフェース部品への参照を持ち、更新(実際には常に更新されるとは限らない)や通知が行えるよう、確実にする必要があります。そしてまた、あらゆるUI部品には適切な通知に登録して、ユーザーインタフェースの変更や生成が起こった際に更新を行うコントローラを、確かに持たなければなりません。

結合コードの簡単な題材を始める事でさえ、実に複雑で長く険しい道になります。 ですが、Max OS X v10.3現在で、私たちはその道を旅する必要はなくなりました。 環境設定が扱う結合コードの殆ど全てを取り除き、代わりに環境設定の情報からUIの要素を自動で更新出来るようになります。 そのためには、Cocoa Bindingを使います。

Cocoa Bindingは、Model-View-Controllerデザインパターンにピッタリな、新しい技術集合です。 様々なViewとModelオブジェクトを繋ぎ、それらの同期処理を任せる事が出来ます。 この処理は、プロパティ名に含まれるキーによって行われます。 あるプロパティ名でView要素が準備されると、Modelオブジェクトも同名のプロパティ名で設定され、この2つのオブジェクトをバインディングが繋ぎます。 これにより、画面上に表示される値と、Modelの中の対応する値の同期を確実に取る事が出来ます。

Cocoa Bindingの一部として提供されるCocoaの新クラスの1つが、NSUserDefaultsControllerクラスです。 このクラスは、Interface Builder上ではShared Defaultsオブジェクトとして表され、Figure 2に示すように結合コードを置き換え、View要素を環境設定システムに格納されるプロパティ名と縛りつけます。


Figure 2: Model-View-ControllerにおけるBindingの位置づけ

ユーザーがUIを操作する度に、Bindingは配下のDefault System中の対応する設定を、確実に更新するでしょう。 また、Bindingはメインユーザーインタフェースの中で、Default Systemに含まれるキーからUIに対して生成されます。 つまりこれは、環境設定を適用するために如何なるコードも書く必要がない、という事を意味します。その上、環境設定ウィンドウでの設定をに確実かつ即座に、アプリケーションに伝達するためのコードを書く必要もありません。

言い換えれば、結合コードとはオサラバです。 書かれていないコードは保守する必要もありませんし、テストする必要もありません。そして、本当に書く必要のあるコード−アプリケーションに特徴的な機能を提供するためのコードを埋没させません。

ユーザーインタフェースの要素を環境設定システムに束縛する方法を説明するために、実際に手を動かしてみましょう。 ユーザーが環境設定で指定した色と大きさで、文字をアプリケーションウィンドウに表示するという単純で小さなアプリケーションを作ります。 Cocoa Bindingが一度に複数の場所で、Viewオブジェクトのプロパティをどのように自動更新するかを示す為に、Document-basedアプリケーションで構築します。

Xcodeを起動し、新しいプロジェクトを作成(メニューから ファイル>新規プロジェクト)します。 新規プロジェクトアシスタントでは、Figure 3に示すように、必ず“Cocoa Document-based Application”を選択して下さい。


Figure 3: 新しいプロジェクトの作成

プロジェクトは、希望の名前を付け好きなフォルダに保存する事が出来ます。 この例では、プロジェクト名として“BindPrefs”を使用しています。 プロジェクトを作成すると、Figure 4に示すようなメインプロジェクトウィンドウが表示されます。


Figure 4: 基本的なプロジェクト

最初に行うちょっとした仕事は、アプリケーションの識別子を変更する事です。 デフォルトでは“com.apple.myApp”に設定されています。 この標準名の代わりに、より相応しい識別子を与えて下さい。 識別子はDefaults Systemが他のアプリケーションの環境設定との区別に使用されるので、識別子の設定は重要です。 また、識別子は~/Library/Preferencesフォルダに格納されるファイル名としても使われます。

識別子を設定する為に、プロジェクトウィンドウのターゲットグループを展開して下さい(Figure 5)。そして、ターゲットの情報ウィンドウを開いて下さい(メニューから プロジェクト>情報を見る またはショートカットの Command+I)。


Figure 5: BindPrefターゲット

Figure 6に示すように、情報ウィンドウでプロパティタブを選択し、識別子を“com.sample.BindPrefs”に変更して下さい。 変更したら情報ウィンドウを閉じても構いません。


Figure 6: BindPrefsターゲットの情報ウィンドウ

いよいよ、ユーザーインタフェースの設定と幾つかのBindingを定義します。 まずアプリケーションの環境設定ウィンドウを設定します。 このウィンドウはアプリケーションのメインnibファイルで設定します。 そのファイルを開く為に、XcodeのプロジェクトウィンドウからMainMenu.nibをダブルクリックして下さい。 Interface Builderが起動し、Figure 7のようなウィンドウを目にする事になるでしょう。


Figure 7: Interface Builder

環境設定ウィンドウ用のパネルを作るには、Cocoa-WindowsパレットからPanelオブジェクトをドラッグします。 空のパネルが1つ現れます。 このパネル上に、Cocoa-Controlsパレットからカラーウェルとスライダーを1つずつドラッグして下さい。 2,3個のテキストフィールドを追加し、Figure 8のような見た目になるように編集して下さい。 示した図そっくりそのままの構成でなくとも、心配する事はありません。今はどこかのデザイン賞受賞を目指しているのではありませんから。


Figure 8: アプリケーションのユーザーインタフェース

次に、ユーザーがメニューから「環境設定」を選んだ際パネルを表示するように、環境設定メニュー項目と環境設定パネルに接続を作る必要があります。 この作業を行うには、MainMenu.nibウィンドウの環境設定メニュー項目からパネルへ、Controlキーを押しながらドラッグします。 それから、Figure 9に示すように、情報ウィンドウで“makeKeyAndOrderFront:”アクションに接続します。


Figure 9: 環境設定メニュー項目の接続

では、環境設定ウィンドウの各種コントロールの設定と、Defaults Systemへの束縛を行いましょう。 カラーウェルコントロールを選択し、情報ウィンドウの一番上のプルダウンメニューからBindingsを選びます。 これにより、Figure 10に示すように、カラーウェルで機能する様々なBindingを利用する事が出来ます。


Figure 10: カラーウェルのBinding情報ウィンドウ

Binding情報ウィンドウは、選択したオブジェクトに束縛可能な様々なプロパティを一覧表示します。 カラーウェルの場合、その値へのアクセス、オブジェクトの有効/無効、非表示か否かの決定が出来ます。

Valueカテゴリのvalueエントリーをクリックし、以下の段階を実行して下さい:

  • Bindチェックボックスをクリックします。すると、MainMenu.nibウィンドウに“Shared Defaults”オブジェクトが出現するでしょう。これはオブジェクトがDefaults Systemに束縛された事を示します。
  • Bind toプルダウンメニューが“Shared User Defaults”に設定して下さい。この操作で、NSUserDefaultsControllerクラスの実体を用いて、カラーウェルをDefaults Systemに束縛します。
  • Controller Keyを“values”に設定します。
  • Model Key Pathテキストフィールドに“textColor”と打ち込みます。これがDefaults Systemに色情報を格納するためのキーとなります。
  • Value Transformerを“NSUnarchiveFromData”に設定します。テキストフィールド右端のプルダウンボタンを使う事で、この値を呼び出す事ができます。NSUnarchiveFromDataを選ばなければならないのは、カラーウェルの値がNSColorオブジェクトだからです。Defaults SystemはNSColorオブジェクトを扱う事が出来ないため、この設定にする事で色情報を、Defaults Systemが扱える形にアーカイバを用いてエンコードします。

これらステップの結果をFigure 11に示します。


Figure 11: カラーウェルのShared Defaultsへの束縛

続いて、大きさスライダーの設定をしましょう。 このスライダーを使って文字の大きさを設定するので、適正な値となるようにしなければなりません。 スライダーを選択し、Attributes情報パネルを開いて下さい。 そして、以下のステップを実行して下さい:

  • minimum valueを8.0に設定します。
  • maximum valueを20.0に設定します。
  • current valueを12.0に設定します。

これらステップの結果をFigure 12に示します。


Figure 12: スライダーの構成

スライダーのBindings情報パネルを開きます。 カラーウェルの時と同じく、多少の設定をしてキーでDefaults Systemと束縛します。 valueエントリーをクリックし、以下のステップを実行して下さい:

  • Bindチェックボックスをクリックします。
  • Bind to:プルダウンメニューを“Shared User Defaults”に設定します。前と同じように、この操作でオブジェクトをDefaults Systemに束縛します。
  • Controller Keyを“values”に設定します。
  • Model Key Pathテキストフィールドに“textSize”と入力します。これがDefaults Systemに格納される文字の大きさ情報のキーとなります。

スライダーの出力は数値なので、Defaults Systemでそのまま扱う事が出来ます。従って、値変換オブジェクトは必要としません。 これらステップの結果をFigure 13に示します。


Figure 13: スライダーのShared Defaultsへの束縛

これでアプリケーションの環境設定パネルの作業は終了です。 今まで行って来た事を見るため、テスト実行してみましょう。

nibファイルを保存します。 nibファイルに含まれる機能はMac OS X v10.2以降と互換性のあるフォーマットでなければ保存出来ない、というダイアログが出現します。 “Save in 10.2 format”ボタンをクリックして下さい。

続いてXcodeに戻り、アプリケーションのビルドと実行を行います。 プロジェクトウィンドウのツールバーにある“ビルドして実行”ボタンをクリックするか、メニューのビルド>ビルドして実行を選択するか、ショートカットのCommand+Rを押して下さい。 すると、プロジェクトのテンプレートから生成されたデフォルトのドキュメントウィンドウが表示される事でしょう。 今のところ、このウィンドウに触る必要はありません。酷くつまらないでしょうから。 これまで手を動かしてきた事の成果を見るには、メニューの環境設定を選び、環境設定パネルを表示します。 Figure 14のように、カラーウェルをクリックし好きな色を設定してみましょう。


Figure 14: 現時点でのアプリケーション

現時点では大して印象的には見えないでしょうが、ここから面白くなって行きます。 一旦アプリケーションを終了し、再起動します。 環境設定パネルを再度開くと、色の設定が先ほどの物のままである事に気付くでしょう。 何度かアプリケーションの実行と終了を繰り返してみて下さい。 その都度、スライダーとカラーウェルの内容を変更してみて下さい。

Cocoa Bindingを利用することで、コードを何一つ書く事なく環境設定ウィンドウを作成しました。 本当に値がDefaults Systemに入出力された事を証明するため、ターミナルウィンドウを開き次のように入力して下さい:

$ defaults read com.sample.BindPrefs

実行例:

{
    	NSColorPanelMode = 6; 
    	NSColorPanelVisibleSwatchRows = 1; 
   	"NSWindow Frame NSColorPanel" = "751 275 201 309 0 0 
   1280 832 "; 
    	textColor = 
    <040b7479 70656473 74726561 6d8103e8 84014084 8484074e 
    53436f6c 
    6f720084 84084e53 4f626a65 63740085 84016301 84046666 66
    66833f 51aa4883 
    3f09523b 833edb7f a50186>; 
   	 textSize = 14.5625; 
}

アプリケーション識別子に、BindPresターゲットで用いた物と同一の物を使用した事に気付くでしょう。 同様に、値に対する2つのキー、textColortextSizeも見られます。 textColorキーは、NSColorオブジェクトが生成したであろうデータブロックを持っています。 textSizeキーは、単純に数値を持っています。

あなたの環境で表示されるこれら2つのキーの値と、上で示した値は、恐らく異なっているでしょう。しかし、環境設定ウィンドウでUIを弄って設定した値が反映されている筈です。 また、NSColorPanelModeNSColorPanelVisibleSwatchRowsといった、2〜3個の他のキーも存在するかもしれません。 これらは、カラーピッカーによって次回起動時に、あなたの残した値として復元されます。

これで、設定をDefaults Systemに読み書きする環境設定ウィンドウの作成が出来ました。今度はこれら値をドキュメントウィンドウに伝達するべく、ドキュメントウィンドウの改造をしましょう。

ドキュメントウィンドウを設定するには、XcodeプロジェクトウィンドウのMyDocument.nibをダブルクリックします。 すると、デフォルトのドキュメントウィンドウが現れます。 Figure 15に示すように、“Your document contents here”文字列をクリックし、Bindings情報パネルを表示します。


Figure 15: ドキュメントウィンドウ

Bindings情報ウィンドウを見ると、文字列で動作するCocoa Bindingが幾分多い事に気付くでしょう。 環境設定ウィンドウはtextSizeキーとtextColorキーで値を格納しているので、fontSizeプロパティとtextColorプロパティにこれらキーの文字列を指定し、束縛します。

fontSizeエントリーを開き、以下のステップを実行します:

  • Bindチェックボックスにチェックします。
  • Bind to:プルダウンに“Shared User Defaults”を設定します。
  • Cotroller Keyテキストフィールドに“values”を設定します。
  • Model Key Pathテキストフィールドを“textSize”と設定します。このキーを記憶に基づいて打ち込むべきではありません。代わりに、テキストフィールドの右端にあるプルダウンボタンを使えるかもしれません。これをクリックすると束縛可能なキーの一覧を表示します(ただしInterface Builderを終了した場合を除く)

これらステップの結果をFigure 16に示します。


Figure 16: テキストフィールドのサイズを束縛

次に、Text ColorグループからtextColorエントリー見つけ、展開して下さい。 情報ウィンドウを多少下にスクロールする必要があるかもしれません。 そして、以下の段階を実行して下さい。

  • Bindチェックボックスをにチェックします。
  • Bind to:プルダウンメニューに“Shared User Defaults”を設定します。
  • Controller Keyに“values”を設定します。
  • Model Key Pathテキストフィールドを“textColor”とします。
  • Value Transformerに“NSUnarchiveFromData”を設定します。思い出して下さい。環境設定ウィンドウでこれを使ったのは、Defaults Systemが色オブジェクトをそのままでは使えなかったからでした。値はDefaults Systemにアーカイブされているので、ここで元に戻す(unarchive)必要があります。

これらステップの結果をFigure 17に示します。


Figure 17: テキストフィールドの色の束縛

これで完成です。 またしてもコードは全く書いていませんが、実際にアプリケーションに多くの機能を追加しました。 動かして設定を弄ってみましょう。

MyDocument.nibファイルを保存します。 再度、例の10.2 nibファイル形式の警告が出るでしょう。 “Save in 10.2 Format”ボタンをクリックして下さい。 続いて、Xcodeに戻り、アプリケーションのビルドと実行をして下さい(Command+R)

恐らく、テキストの色がもはや黒ではなくなっている事に気付くでしょうが、その色は環境設定で最後に設定した色です。 環境設定ウィンドウを開き、新しい色を選んで下さい。 Figure 18に示すように、ドキュメントウィンドウのテキストの色が、選択色の変化に追従する事が分かります。 文字サイズでも遊んでみましょう。 新しいドキュメントウィンドウを開き、複数ウィンドウが同時に更新される様子を見て下さい。


Figure 18: アプリケーションの実行

環境設定と関連する全てのアプリケーション項目の同期を保つ手段として、本記事の始めにどう述べたか思い出して下さい。 「かつては相当量の結合コードを必要とした」でしたね? Cocoa Bindingを使う事で、結合コードは一切使われませんでした。 スコアを保持し続けるのに、1行もコードを書く必要はない事に気付くでしょう(If you've been keeping score, you'll notice that not one line of code has been written.)。

さて、あなたが興奮し過ぎる前に、Cocoa Bindingによるアプリケーションの環境設定の扱いには、いくつかの制限がある事を述べます。 まず、Cocoa BindingはPantherにしか搭載されていない事です。 新しくアプリケーションを作る場合、これは問題ではないでしょう。 しかし、もしMac OS X 10.2以前で動かねばならないアプリケーションを作る場合、Cocoa Bindingは使えません。

また、Cocoa Bindingは新技術であり、システムへの導入過程の途中にあります。 Application Kitのコントロールに含まれる多くのプロパティはCocoa Bindingに対応していますが、対応していないプロパティも数多くあります。 対応していないプロパティに束縛することも可能ではありますが、多少のコードを書く必要があります。 しかしながら、将来、Cocoa Bindingが成熟する時、上手くいけば様々なUI部品のプロパティに、いよいよアクセスできるようになるでしょう。

更新日: 2005-01-05

  • translation/adc/cocoa/foundation/cocoa_bindings/binding_your_preferences_in_cocoa.txt
  • 最終更新: 2015-01-06 11:51
  • (外部編集)