• 検索結果がありません。

2003 Apple Computer, Inc. (Last Updated May 7, 2003)

N/A
N/A
Protected

Academic year: 2021

シェア "2003 Apple Computer, Inc. (Last Updated May 7, 2003)"

Copied!
31
0
0

読み込み中.... (全文を見る)

全文

(1)

プログラミングトピック:

オブジェクトとの通信

「オブジェクトとの通信」では、Cocoa オブジェクト間の通信を支援する Cocoa の主要なデ ザインパターンについて説明します。これらのメカニズムとパラダイムには、委任、通知、 ターゲット/アクション、キー/値コーディングが含まれます。 重要 このプログラミングトピックはまだ暫定版の段階です。掲載されている情報は正確ですが、将 来更新される可能性があります。

ディスカッション

Cocoa とそのオブジェクト指向言語である Objective-C と Java では、プログラム固有の動作 を追加する 1 つの方法として、継承があります。既存のクラスのインスタンスの属性と動作を 拡張、または何らかの方法で変更するサブクラスを作成します。ただしプログラムを特徴付け る特殊なロジックを追加する他の方法もあります。また、Cocoa オブジェクトの機能を再利用 して拡張するメカニズムもあります。 プログラム内のオブジェクト間の関係は多岐の次元に渡ります。継承の階層構造があります が、プログラム中のオブジェクトは動的にも存在します。プログラムの作業を実行するため に、実行時に相互に通信する必要のある他のオブジェクトのネットワークの中などにです。 オーケストラの演奏者と同様に、プログラム内のオブジェクトにはそれぞれの役割、すなわち プログラムに提供する一定の範囲の動作があります。マウスのクリックに応答して楕円形の サーフェスを表示したり、オブジェクトのコレクションを管理したり、ウインドウの存続期間 中の主要なイベントを調整するなどです。設計どおりのことを実行するだけで、それ以上のこ とはしません。しかし、その効果をプログラム内で発揮するには、各オブジェクトが他のオブ ジェクトと通信できなければなりません。他のオブジェクトにメッセージを送信したり、他の オブジェクトからメッセージを受信したりといったことができなければならないのです。 オブジェクトが他のオブジェクトにメッセージを送信するには、送信先のオブジェクトへの参 照を持っているか、何らかの配信メカニズムが用意されている必要があります。Cocoa では、 オブジェクトが相互に通信するための多数の方法を用意しています。そのメカニズムとテク ニックは、堅牢なアプリケーションを効率よく構築できるようにするためのデザインパターン で構成されています。デザインパターンは単純なものから若干複雑なものまでさまざまあり、 サブクラス化よりも望ましい選択肢となることもしばしばあります。デザインパターンの多く は、オブジェクトの構成、すなわち複雑で高度にカスタマイズした動作をさせるためにオブ

(2)

ジェクトを組み合わせる(構成する)広範なテクニックをベースにしています。Interface Builder では、それらをプログラミングによって、また時にはグラフィカルに構成できます。 このプログラムトピックでは、 このような Cocoa のデザインパターンの得に重要な事柄につ いて説明します。

(3)

アウトレット(Outlet)

オブジェクト構成はダイナミックなパターンであり、オブジェクトは、その構成要素である他 のオブジェクトへの参照を何らかの方法で取得し、メッセージを送信できるようにする必要が あります。一般に、このような他のオブジェクトはインスタンス変数として保持されます。イ ンスタンス変数は、プログラム実行中のある時点で、適切な参照で初期化する必要がありま す。 アウトレットは、オブジェクトのインスタンス変数のようなものですが、参照の設定とアーカ イブを、Interface Builder を通じて行います。オブジェクトとそのアウトレットの間の接続 は、アウトレットを内包するオブジェクトがインスタンス化されるたびに確立されます。アウ トレットを内包するオブジェクトは、アウトレットを IBOutlet という型修飾子を付けてイン スタンス変数として保持します。たとえば、次のようになります。

@interface AppController : NSObject {

IBOutlet NSArray *keywords; } アウトレットはインスタンス変数であるため、オブジェクトのカプセル化されたデータの一部 になります。しかし、アウトレットは単なるインスタンス変数ではありません。オブジェクト とそのアウトレットの間の接続は nib ファイルにアーカイブされます。nib ファイルがロード されるときに、各接続がアンアーカイブされて維持されるため、他のオブジェクトにメッセー ジを送信する必要があるときにはいつでも利用できます。

型修飾子 IBOutlet は、開発中の Interface Builder アプリケーションがアウトレットの表示と 接続を Project Builder と同期できるようにするために、インスタンス変数の宣言に適用され るタグです。つまりカスタムオブジェクトのアウトレットを追加・接続したあとで、定義され たアウトレットを使ってヘッダファイルを生成できるということです。さらに、Project Builder で、ヘッダファイルの中で(IBOutlet 識別子を使って)アウトレットを宣言できま す。Interface Builder はこのような新しい宣言を取得できるため、これらを接続し、接続情報 を nib ファイルに格納できます。図 4-1 は、Interface Builder でアウトレットを接続する方 法を示しています。

(4)

図 4-1 Interface Builder におけるアウトレットの接続 アプリケーションは、一般に、そのカスタムコントローラオブジェクトとユーザインタフェー ス上のオブジェクトの間のアウトレット接続を設定しますが、これらの接続は、Interface Builder でインスタンスとして表現できる任意のオブジェクトの間で、たとえ 2 つのカスタム オブジェクトの間でも作成できます。インスタンス変数と同様に、それをクラスに含めること が正しいという根拠が必要になります。オブジェクトのインスタンス変数が多いほど、より多 くのメモリを占有することになるためです。オブジェクトを参照する別の方法がある場合、た とえば、行列のインデックス位置を通じての検索、関数パラメータとして含めることによる検 索、タグの使用による検索などができる場合は、その方法を採用してください。

(5)

委任(delegate)とデータソース

次のセクションでは、委任とデータソース、およびそれらが一部を構成している委任のデザイ ンパターンについて説明します。 このセクションの内容: 委任とは? 委任の仕組み 委任メッセージの形式 委任と Application Kit データソース

委任とは?

委任とは、プログラム内でオブジェクトが何らかのイベントに遭遇したときに、そのオブジェ クトに代わって、またはそのオブジェクトと連携して機能するオブジェクトです。結果的にそ のイベントに対するユーザインタフェースの制御を委任されるオブジェクトです。 委任の価値をより深く理解するには、ウインドウ(NSWindow のインスタンス)やテーブル ビュー(NSTableView のインスタンス)など、既製の Cocoa オブジェクトに注目するとよい でしょう。これらのオブジェクトは、一般的な方法で特定の役割を果たすように設計されてい ます。たとえば、ウインドウオブジェクトは、物理的なウインドウの終了、リサイズ、移動な ど、そのコントロールとハンドルのマウス操作に応答します。このように限定された一般的な 動作は、必然的に、イベントがアプリケーションの他の部分に与える(または与えることが予 想される)影響について、オブジェクトが認識できることを制限します。特に影響を受ける動 作がアプリケーション固有のものである場合はなおさらです。委任は、カスタムオブジェクト がアプリケーション固有の動作を既製のオブジェクトに伝える手段を提供します。 委任のプログラミングメカニズムは、プログラム内のどこかほかの場所で生じた変化(通常は ユーザアクションにより引き起こされる変化)に伴い、自身の外観と状態を調整する機会をオ ブジェクトに提供するというものです。さらに重要なことに、委任により、オブジェクトは、 そのオブジェクトから継承させることなく、ほかのオブジェクトの動作を変更できます。委任 はほとんどの場合カスタムオブジェクトの 1 つで、定義上は、汎用の、委任する側のオブジェ クトだけでは認識できないようなアプリケーション固有のロジックが組み込みまれています。

(6)

委任の仕組み

委任メカニズムの設計は単純です(図 1-1)。委任する側のクラスには、アウトレット(通常 は delegate という名前が付けられている)があり、このアウトレットを設定してアクセスす るメソッドも含まれています。さらにそのメソッドのいくつかを宣言し(実装はしない)、そ れらが「簡易プロトコル」を構成します。簡易プロトコルは一般に、委任する側のクラスのカ テゴリとして生じますが、委任ですべてのメソッドをプロトコルに実装する必要がないという 点で正式なプロトコルと異なります。委任は、それ自身が委任する側のオブジェクトと連携し たり、オブジェクトのデフォルトの動作に作用することに関心がある場合は、簡易プロトコル からなるメソッドだけを実装します。 重要 委任を使っている Cocoa クラスを継承する場合、その委任をサブクラスに明示的には保持し ないでください。委任する側のオブジェクトは、その委任を「所有」していると見なされてい るわけではないので、それらを保持すべきではありません。慣例により、Cocoa オブジェクト はそれらの委任を保持しません。 図 1-1 委任のメカニズム 簡易プロトコルのメソッドは、委任する側のオブジェクトによって処理または予想された重要 なイベントに注目します。このオブジェクトは、これらのイベントを委任に伝達するか、進行 中のイベントの場合は委任からの入力や承認を要求することを望んでいます。たとえば、ユー ザがウインドウのクローズボタンをクリックすると、ウインドウオブジェクトは windowShouldClose: メッセージをその委任に送信します。これにより、たとえばウインド ウが保存する必要のあるデータと関連している場合は、委任にウインドウのクローズを拒否ま たは延期する機会が与えられます(図 1-2 を参照)。ウインドウが閉じられると、ウインドウ オブジェクトはwindowWillClose: メッセージを委任に送信し、ウインドウ専用のリソースを 解放するなど、その時点で適切なことを実行する機会を委任に与えます。

(7)

図 1-2 委任に関する現実的なシーケンス 委任する側のオブジェクトがメッセージを送信するのは、委任がそのメソッドを実装している 場合に限られるということを強調しておかなければなりません。これを調べるには、最初に、 委任で NSObject メソッドの respondsToSelector: を呼び出します。この事前のチェック が、簡易プロトコルの設計の鍵となります。

委任メッセージの形式

委任メソッドの形式はあらかじめ決められています。委任メソッドは、委任を実行する Application Kit オブジェクト(アプリケーション、ウインドウ、コントロールなど)の名前 で始まります。この名前は小文字で、「NS」プレフィックスは付いていません。通常(常にで はない)、このオブジェクト名の次に、報告されたイベントの時間軸上での状態を示す助動詞 が続きます。すなわち、この助動詞は、イベントが発生しそうなのか(「Should」または 「Will」)、それともすでに発生したのか(「Did」または「Has」)を示します。この時間 軸上での区別は、戻り値を期待しているメッセージと期待していないメッセージを分類するの に役立ちます。リスト 1-1 には、戻り値を期待している Application Kit の委任メソッドをい くつか示します。 リスト 1-1 戻り値のある委任メソッドのサンプル

- (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename; - (BOOL)textShouldBeginEditing:(NSText *)textObject; - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; - (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)newFrame;

(8)

これらのメソッドを実装している委任は、進行中のイベントを(最初の 2 つで NO を返すこ とで)ブロックしたり、(applicationShouldTerminate: メソッドでNSTerminateLater を 返すことで)延期したり、推奨されるパラメータ(最後のメソッドのフレーム矩形)を変更し たりできます。 他の種類の委任メソッドは、戻り値を期待せず、void を返すように入力されたメッセージで呼 び出されます。このようなメッセージは単に情報を提供するもので、メソッド名にはしばしば 「Did」など、イベントが経過したことを示す情報が含まれています。リスト 1-2 に、このよ うな委任メソッドの例をいくつか示します。 リスト 1-2 void を返す委任メソッドのサンプル - (void) tableView:(NSTableView*)tableView mouseDownInHeaderOfTableColumn:(NSTableColumn *)tableColumn; - (void)applicationDidUnhide:(NSNotification *)notification; - (void)applicationWillBecomeActive:(NSNotification *)notification; - (void)windowDidMove:(NSNotification *)notification; この最後のメッセージ群については、2 つのことに注目してください。まず、(3 番目のメ ソッドにあるような)「Will」という助動詞は、戻り値が期待されていることを意味します。 この場合、イベントは進行中でブロックできませんが、このメッセージによって委任には、そ のイベントのためのプログラムを準備する機会が与えられます。 その他の注目すべき点は、最後の 3 つのメソッドと関係があります。これらのメソッドのそれ ぞれの唯一のパラメータは NSNotification オブジェクトで、それらが特定の通知を発行した 結果として呼び出されることを意味します。たとえば、windowDidMove: メソッドは、 NSWindow メソッドのNSWindowDidMoveNotification と結び付いています。通知につい ては「通知」のセクションで詳しく説明しますが、ここでは通知と委任メッセージとの関係を 理解することが重要です。委任する側のオブジェクトは自動的に、その委任を、発行したすべ ての通知のオブザーバに仕立てます。委任が実行する必要があるのは、その通知を受けるため の関連メソッドを実装することだけです。 カスタムクラスのインスタンスを Application Kit オブジェクトに委任するには、そのインス タンスを Interface Builder の delegate アウトレットに単純に接続します。または委任する 側のオブジェクトの setDelegate: メソッドを使用して、awakeFromNib メソッドなどで、 なるべく早期にプログラムで設定することができます。

(9)

委任する側のオブジェクトは(必ずではありませんが)たいていは、NSApplication、 NSWindow、または NSView オブジェクトです。委任オブジェクトは(必ずではありません が)たいていは、アプリケーションの一部を制御するために作成されたカスタムオブジェクト です(コントローラオブジェクトと呼ばれます)。表 1-1 は、委任を定義する Application Kit クラスを示しています。 表 1-1 Application Kit クラスと委任 NSText NSOutlineView NSDrawer NSTabView NSMatrix NSControl NSWindow NSTableView NSFontPanel NSBrowser NSTextField NSSplitView NSFontManager NSApplication いくつかの Application Kit クラスは、「モーダル委任」と呼ばれる、制限されたタイプの委 任を使います。このようなクラスのオブジェクト(NSOpenPanel など)は、ユーザがダイア ログの「OK」ボタンをクリックしたときに、指定された委任のハンドラメソッドを呼び出す モーダルダイアログを実行します。モーダル委任は、モーダルダイアログの操作の範囲に限定 されます。 委任には、ほかにもプログラム上の用途があります。たとえば、委任を使うと、同じプログラ ム内の 2 つのコントローラオブジェクトが、互いを探しあてて通信するのが簡単になります。 たとえば、アプリケーション全体を制御するオブジェクトは、次のようなコードを使って、ア プリケーションのインスペクタウインドウ(それが現在のキーウインドウと仮定すると)のコ ントローラを見つけることができます。

id winController = [[NSApp keyWindow] delegate];

また、次のようなコードを実行することで、アプリケーションコントローラオブジェクト(つ まり、グローバルなアプリケーションインスタンスの委任)を見つけることができます。

id appController = [NSApp delegate];

データソース

データソースは委任に似ていますが、ユーザインタフェースの制御ではなく、データの制御を 委任されます。データソースは、テーブルビューやアウトラインビューなど、可視データの行 を代入するためのソースを必要とする NSView オブジェクトによって保持されるアウトレッ

(10)

トです。ビューのデータソースは、通常はその委任として機能するオブジェクトと同じオブ ジェクトですが、どのようなオブジェクトでも構いません。委任と同様に、データソースは ビューに必要なデータを供給し、もっと高度な実装では、そのようなビューでユーザが直接編 集するデータを処理するために、簡易プロトコルのメソッドを 1 つ以上実装する必要がありま す。

(11)

通知(Notification)

次のセクションでは、通知のデザインパターン、およびプログラムのオブジェクトにイベント の通知をブロードキャストするシステムについて説明します。 このセクションの内容: 通知のメカニズム 委任と通知 通知オブジェクト 通知センター 通知キュー

通知のメカニズム

オブジェクト間で情報を受け渡す標準的な方法はメッセージの受け渡しです。すなわち、ある オブジェクトが別のオブジェクトのメソッドを呼び出します。しかし、メッセージの受け渡し では、メッセージを送信するオブジェクトは受信側が何であり、どのメッセージに応答するか を知っている必要があります。このような要件は、委任メッセージだけでなく、他のタイプの メッセージにも当てはまります。2 つのオブジェクトをこのように緊密に結び付けることは、 極端にいうと、2 つの独立したサブシステムを 1 つにまとめることになるので、望ましくない 場合もあります。また、アプリケーション内のさまざまなオブジェクト間にハードコードされ た接続が必要になるため、実用的とはいえません。 標準的なメッセージの受け渡しだけでは間に合わない場合のために、Cocoa ではブロードキャ ストによる通知を用意しています。この通知メカニズムを使用することで、オブジェクトは、 それが何を実行しているかを、他のオブジェクトに通知し続けることができます。この点で は、通知は委任に似ていますが、その違いは重要です。委任と通知の重要な違いは、委任は (委任する側のオブジェクトとその委任の間の)通信経路が 1 対 1 であることです。一方、 通知は潜在的に 1 対多の通信形態、すなわちブロードキャストです。オブジェクトは、委任は 1 つしか保持できませんが、通知の場合は受信者が分かっているので、多数の「オブザーバ」 を保持できます。また、オブジェクトは、それらのオブザーバが何かを知っている必要もあり ません。任意のオブジェクトが通知によってイベントを直接監視し、イベントに応じて自身の 外観、動作、状態を調整できます。プログラム内で調整と結合を実現するには、通知は強力な メカニズムです。

(12)

通知メカニズムの仕組みは、概念的には単純です。プロセスには通知センターというオブジェ クトがあり、通知のためのクリアリングハウスであり放送局の役割を果たします。アプリケー ションのどこかほかの場所で発生するイベントについて知る必要のあるオブジェクトは、イベ ントが発生したときに通知してくれるよう通知センターに登録します。たとえば、コントロー ラオブジェクトは、ポップアップが選択されたときに、その変化を認識してユーザインタ フェースに反映できなければなりません。イベントが発生すると、そのイベントを処理するオ ブジェクトが通知センターに通知を送り、センターがそのオブザーバすべてに通知を配信しま す。図 3-1 にこのメカニズムを示します。 注意:通知センターは、そのオブザーバに同時に通知を配信します。すべての通知が送信され るまで、送信側のオブジェクトには制御は戻りません。通知を非同期にブロードキャストする には、通知キューを使用する必要があります(「通知キュー」を参照)。通知キューは、指定 された通知を遅らせ、指定された何らかの基準に従って類似した通知を結合させてから、通知 センターに通知を送信します。 図 3-1 通知の送信とブロードキャスト 任意のオブジェクトが通知を送信でき、自身を通知のオブザーバとして通知センターに登録す ることができます。通知を送信するオブジェクト、通知に含まれるオブジェクト、および通知 のオブザーバはすべて別々のオブジェクトでも、同じオブジェクトでも構いません。(送信側 のオブジェクトと監視するオブジェクトを同じにすると、アイドル時間の処理などに役に立ち ます)。通知を送信するオブジェクトは、オブザーバについて知る必要はありません。これに 対して、オブザーバは少なくとも通知名と、通知オブジェクトによってカプセル化されたディ クショナリのキーを知る必要があります。(通知オブジェクトの構成については、「通知オブ

(13)

ジェクト」を参照してください)。

委任と通知

前述のとおり、通知モデルと委任モデルの主要な違いは、通知がブロードキャストメカニズム であるのに対して、委任が 1 対 1 の関係であるということです。しかし、その他にも違いが あるため、場合によって通知が有利であったり、委任が有利になったりします。 ・配信された通知を処理するメソッドは、値を返すことができません。通知メソッドは、次の シグネチャを持つ必要があります: - (void)notificationHandlerName:(NSNotification *); この要件により、監視するオブジェクトは元のイベントに直接影響を与えることができませ ん。しかし、委任は委任する側のオブジェクトがイベントを処理する方法にしばしば影響を与 えます。 ・Application Kit オブジェクトの委任となるオブジェクトは、自動的に通知のオブザーバと して登録されます。必要なのは、Application Kit クラスでその通知に対して定義した通知メ ソッドを実装することだけです。 ・通知を送信するオブジェクトは、オブザーバの存在を知る必要さえありません。 ・オブジェクトは、事前に定義された委任メソッドだけでなく、通知センターから任意のメッ セージを受信できます。つまりアプリケーションは、それが適していると認めた任意の方法 で、自身の通知名とメソッドを定義できます。

通知オブジェクト

通知はオブジェクトであり、NSNotification のインスタンスです。このオブジェクトは、 フォーカスを獲得しているウインドウやネットワーク接続の終了など、イベントに関する情報 をカプセル化します。イベントが発生すると、イベントを処理するオブジェクトが通知セン ターに通知を送信し、その通知が即座にセンターから登録されているすべてのオブジェクトに ブロードキャストされます。 NSNotification オブジェクトには、名前、オブジェクト、およびオプションディクショナリが 含まれています。名前は通知を識別するタグです。オブジェクトは、通知の送信側が、その通

(14)

知のオブザーバに送信したいオブジェクトです(通常は、通知を送信したオブジェクトで す)。これは委任メッセージの送信側オブジェクトに似ており、受信側は詳細をこのオブジェ クトに照会することができます。ディクショナリは、イベントに関する情報を格納していま す。

通知センター

通知センターは通知の送受信を管理します。特定の基準に合った通知をすべてのオブザーバに 知らせます。通知情報は、NSNotification オブジェクトにカプセル化されています。クライア ントオブジェクトは、他のオブジェクトによって送信される特定の通知のオブザーバとして、 自身を通知センターに登録します。イベントが発生すると、オブジェクトは適切な通知を通知 センターに送信します。通知センターは、登録されている各オブザーバにメッセージを配信 し、唯一の引数として通知を受け渡します。送信するオブジェクトと監視するオブジェクトが 同じ場合もあります。 Cocoa には、2 種類の通知センターがあります。 ・通知センター(NSNotificationCenter のインスタンス)は、シングルタスク内で通知を管理 します。 ・分散通知センター(NSDistributedNotificationCenterのインスタンス)は、単一のコン ピュータ上で複数のタスクの通知を管理します。

NSNotificationCenter

各タスクには、NSNotificationCenter クラスメソッドの defaultCenter でアクセスするデ フォルトの通知センターがあります。この NSNotificationCenter は、シングルタスク内の通 知を処理します。同じマシン上のタスク間の通信ついては、分散通知センターを使用してくだ さい(「NSDistributedNotificationCenter」を参照)。 通知センターはオブザーバに同時に通知を配信します。つまり、通知を送信すると、すべての オブザーバが通知を受信して処理するまで、送信側に制御が戻りません。通知を非同期に送信 するには、通知キューを使用します(「通知キュー」を参照)。 マルチスレッド型のアプリケーションでは、通知は必ず、それが送信されたスレッド内で配信 されます。オブザーバが自身を登録したスレッドと同じでなくても構いません。

(15)

NSDistributedNotificationCenter

各タスクには、NSDistributedNotificationCenter クラスメソッドの defaultCenter でアクセ スできるデフォルトの分散通知センターがあります。この分散通知センターは、単一マシン上 のタスク間で送信できる通知を処理します。異なるマシン上のタスク間の通信については、分 散オブジェクトを使います(「Distributed Objects」を参照)。 分散通知の送信は高価な処理になります。通知はシステム全体のサーバに送信されてから、分 散通知の対象としてオブジェクトを登録しているすべてのタスクに配信されます。通知を送信 してから、それが別のタスクに届くまでの待ち時間に制約はありません。実際、大量の通知が 送信されて、サーバのキューがいっぱいになった場合は、通知が欠落することもあります。 分散通知は、タスクの実行ループを通じて配信されます。分散通知を受信するには、タスク は、NSDefaultRunLoopMode などの何らかの「一般的な」モードで実行ループを実行してい なければなりません。受信側のタスクがマルチスレッド化されている場合は、通知がメインの スレッドに届くことを想定しないでください。通知はたいていメインのスレッドの実行ループ に配信されますが、他のスレッドが通知を受信する可能性もあります。 通常の通知センターの場合は任意のオブジェクトが通知オブジェクト(通知でカプセル化した オブジェクト)になれますが、分散通知センターの場合は、通知オブジェクトは NSString オ ブジェクトに限られます。送信側のオブジェクトとオブザーバは異なるタスク内にある可能性 もあるため、通知には任意のオブジェクトへのポインタを含むことはできません。このため分 散通知センターの場合は、通知は通知オブジェクトとして文字列を使用する必要があります。 通知の照合は、オブジェクトポインタではなく、この文字列を使って行われます。

Foundation フレームワークの NSNotificationCenter クラスは、Core Foundation の不透過 (opaque)型である CFNotificationCenter がそのままベースになっています。このため、2 種類のオブジェクト間には「toll-free bridge」があります。つまり、Cocoa プロセスは、 Carbon プロセスが(CFNotificationCenter オブジェクトを通じて)受信できる通知を送信で き、その逆も同様です。

通知キュー

NSNotificationQueue オブジェクト(通知キュー)は、通知センター (NSNotificationCenter のインスタンス)のバッファの役割を果たします。通知キューは、一 般に FIFO(先入れ先出し)の順番で通知(NSNotification)を保持します。通知がキューの 先頭に来ると、キューがそれを通知センターに送信し、次にオブザーバとして登録されている すべてのオブジェクトに通知が配信されます。

(16)

どのスレッドにも、タスクのデフォルト通知センターと結び付いているデフォルトの通知 キューがあります。独自の通知キューを作成し、センターやスレッドごとに複数のキューを保 持することができます。 図 3-2 通知キューと通知センター

通知の結合

NSNotificationQueue クラスは、Foundation Kit の通知メカニズムに 2 つの重要な機能を提 供します。すなわち、通知の結合と非同期の送信です。結合は、キューに入ったばかりの通知 に類似した通知を、キューから削除する処理です。新しい項目が、すでにキューに入っている 通知に類似している場合、新しいものはキューには入れられず、類似した通知がすべて (キューの先頭にあるものは除いて)削除されます。ただし、このように特殊な結合の動作に は依存しないでください。 類似性の基準を指定するには、 enqueueNotification:postingStyle:coalesceMask:forModes: メソッドの第 3 引数に以下 の定数を指定します(複数も可)。 NSNotificationNoCoalescing NSNotificationCoalescingOnName NSNotificationCoalescingOnSender NSNotificationCoalescingOnName と NSNotificationCoalescingOnSender 定数を

(17)

使ってビットごとの OR 演算を実行し、通知名と通知オブジェクトを使用した結合を指定でき ます。

通知の非同期送信

NSNotificationCenter の postNotification: メソッドとそのバリエーションを使って、通知セ ンターにすぐに通知を送信できます。しかし、メソッドの呼び出しは同期しています。送信側 のオブジェクトがその実行のスレッドを再開するには、通知センターがすべてのオブザーバに 通知を配信して戻ってくるまで、待つ必要があります。しかし、NSNotificationQueue メソッ ドの enqueueNotification:postingStyle: と enqueueNotification:postingStyle:coalesceMask:forModes: メソッドを使えば、通知を キューに入れて非同期で送信できます。これらのメソッドは、通知をキューに入れると、すぐ に呼び出し元オブジェクトに戻ってきます。 通知キューが空にされ、エンキューメソッドで指定された送信スタイルと実行ループモードに 基づいて通知が送信されます。モード引数は、キューを空にするための実行ループモードを指 定します。たとえば、NSModalPanelRunLoopMode を指定すると、実行ループモードがこの モードにある場合にのみ、通知が送信されます。実行ループが現在このモードにない場合、通 知は次にこのモードに入るまで待機します。 通知キューへの送信は、3 つのスタイル、すなわち NSPostASAP(できるだけ早く送信)、 NSPostWhenIdle(待機時に送信)、NSPostNow(すぐに送信) のいずれかで起こる可能性 があります。これらのスタイルについては、以下のセクションで説明します。 できるだけ早く送信 現在の実行ループモードが要求されたモードに一致している場合に、NSPostASAP スタイルで キューに入れられた通知は、実行ループの現在の繰り返しが完了したときに通知センターに送 信されます(要求されたモードと現在のモードが異なる場合は、通知は要求されたモードに 入ったときに送信されます)。実行ループは、1 回の繰り返しの間に何度も呼び出せるため、 現在の呼び出しが終了して、実行ループに制御が戻ったあと、すぐには配信されないこともあ ります。まず、タイマーやソースの解放、他の非同期通知の配信など、他の呼び出しが先に行 われます。 ディスプレイサーバなどの高価なリソースには、一般に NSPostASAP の送信スタイルを使用 します。多数のクライアントが実行ループからの呼び出し時にウインドウバッファ上に描画し ている場合、描画動作のたびにバッファをディスプレイサーバにフラッシュするのは高くつき ます。このような状況では、それぞれの draw... メソッドによって、指定された名前とオブ

(18)

ジェクトに基づく結合と、NSPostASAP 送信スタイルが設定された「FlushTheServer」などの 通知がキューに入れられます。その結果、これらの通知のうち 1 つだけが実行ループの最後に 配信され、ウインドウバッファが一度だけフラッシュされます。 待機時に送信 NSPostWhenIdle スタイルでキューに入れられた通知は、実行ループが待機状態のときにの み送信されます。この状態では、タイマーにしろ他の非同期イベントにしろ、実行ループの入 力チャネルには何もありません。NSPostWhenIdle スタイルを使ったキューの典型的な例 は、ユーザがテキストを入力し、プログラムがそのテキストの量をバイト数としてどこかに表 示する場合などです。ユーザが文字を入力するたびに(特にユーザの入力が速い場合は)、テ キストフィールドのサイズを更新するのは非常に高くつきます(しかも、あまり役に立ちませ ん)。このような場合、プログラムは文字が入力されるたびに、結合を有効にし(結合の結 果)送信スタイルをNSPostWhenIdle に設定した「ChangeTheDisplayedSize」などの通知 をキューに入れます。ユーザが入力を停止し、実行ループが待機状態に入ると、キューに内の 1 つの「ChangeTheDisplayedSize」通知が送信され、ディスプレイが更新されます。終了間 近の実行ループ(入力チャネルがすべて終了したときに発生する)は待機状態ではないため、 通知は送信されません。 即座に送信 NSPostNow でキューに入れられた通知は、結合のあとすぐに通知センターに送信されます。 非同期の呼び出し動作を必要としない場合は、NSPostNow を使って通知をキューに入れます (すなわち、NSNotificationCenter メソッドの postNotification: を使って送信します)。多 くのプログラミング状況では、同期動作が可能なだけでなく、望ましいのです。配送後に通知 センターから戻るようにすることで、オブザーバオブジェクトが通知を受信して処理したこと を確認できます。もちろん、結合によって削除したい類似の通知がキューにある場合は、 postNotification: ではなく、enqueueNotification... と NSPostNow を使用します。

(19)

ターゲット/アクションパラダイム

次のセクションでは、コントロールとプログラム中の他のオブジェクトとの通信のための、 Cocoa の重要なデザインパターンであるターゲット/アクションのパラダイムについて説明し ます。 このセクションの内容: はじめに コントロール、セル、メニュー項目 ターゲット アクション Application Kit で定義されたアクション ターゲットとアクションの設定

はじめに

委任と通知は、プログラムのオブジェクト間の一定の形式のやり取りを処理するのには役立ち ますが、最も頻繁に発生する種類の通信に特に適しているとはいえません。典型的なアプリ ケーションのユーザインタフェースは、いくつかのグラフィカルオブジェクトで構成され、そ の中で最も一般的なオブジェクトはおそらくコントロールでしょう。コントロールは、現実 の、または論理上のデバイスをグラフィカルに表現したものです(ボタン、スライダ、チェッ クボックスなど)。現実のコントロール(ラジオのチューナーなど)と同様に、コントロール を使用して、それが含まれている何らかのシステム(この場合はアプリケーション)に、自分 の意図を伝達します。 ユーザインタフェースにおけるコントロールの役割は単純です。それはユーザの意図を解釈 し、他のオブジェクトにその要求を実行するよう指示します。たとえばユーザがクリックした り、Return キーを押したりしてコントロールに働きかけると、ハードウェアデバイスは生のイ ベントを生成します。コントロールはそのイベントを(Cocoa 向けに適切にパッケージ化され た状態で)受け取り、それをアプリケーション固有の命令に翻訳します。しかし、イベントだ けではユーザの意図に関する十分な情報は得られません。それらは単に、ユーザがマウスボタ ンをクリックしたり、キーを押したりしたことを伝えるだけだからです。そこで、イベントと 命令間の翻訳を行うために、何らかのメカニズムが必要です。そのようなメカニズムのベース になるのがターゲット/アクションパラダイムです。

(20)

Cocoa では、コントロールと他のオブジェクト間の通信にターゲット/アクションメカニズム を利用しています。このメカニズムにより、コントロールとそのセル(または複数のセル)は アプリケーション固有の命令を適切なオブジェクトに送信するのに必要な情報をカプセル化で きます。受信側オブジェクトは、一般にカスタムクラスのインスタンスで、ターゲットと呼ば れています。アクションは、コントロールがターゲットに送信するメッセージです。ユーザイ ベントに関心のあるオブジェクト、つまりターゲットがメッセージに意味を与え、その意味が 多くの場合、アクションに付けられる名前に反映されます。

コントロール、セル、メニュー項目

ほとんどのコントロールは、NSControl クラスを継承するオブジェクトです。コントロールに は、アクションメッセージを最初にそのターゲットに送信する役割を担いますが、メッセージ を送信するのに必要な情報を持っていることはまれです。このため、多くの場合は、セル(ま たは複数のセル)に頼ることになります。 コントロールはほとんどの場合、1 つまたは複数のセル(NSCell から継承したオブジェク ト)が関連付けられています。なぜそのような関連付けを行っているのでしょうか?コント ロールは、NSView クラスと NSResponder クラスも含め、その祖先のインスタンス変数の組 み合わせをすべて継承しています。コントロールは高くつくので、セルを使って、画面上でコ ントロールが占める領域をさまざまな機能分野に分割します。セルは軽量のオブジェクトで、 コントロールの一部または全部と重なるものと考えることができます。しかし、セルは領域を 区切っているだけでなく、役割を分けるものでもあります。セルは本来ならコントロールが実 行する描画の一部を実行し、本来ならコントロールが持つデータの一部を保持します。このよ うなデータの、2 つの項目がターゲットとアクションのインスタンス変数です。図 5-1 に、コ ントロール/セルのメカニズムを示します。 NSControl と NSCell はどちらも抽象クラスであるため、ターゲットとアクションのインスタ ンス変数の設定を完全には処理できません。デフォルトでは、NSControl は関連したセルがあ る場合に、単純に情報をそのセルに設定するだけです(NSControl はそれ自身とセル間の 1 対 1 のマッピングしかサポートしていませんが、NSMatrix のような NSControl のサブクラ スは複数のセルをサポートしています)。デフォルトの実装では、NSCell は単に例外を引き 起こすだけです。ターゲットとアクションの設定処理を実際に実装しているクラス (NSActionCell)を見つけるには、継承チェーンを 1 つ下る必要があります。 NSActionCell から派生したオブジェクトは、ターゲットとアクションの値をそれらのコント ロールに提供することで、そのコントロールがアクションメッセージを作成して適切な送信先 に送信できるようにしています。NSActionCell オブジェクトは、マウス(カーソル)の追跡 を処理するために領域をハイライトするとともに、指定したターゲットにアクションメッセー ジを送信するための制御を支援します。ほとんどの場合、NSControl オブジェクトの外観と動

(21)

作は、対応する NSActionCell オブジェクトに完全に任されます(NSMatrix とそのサブクラ スの NSForm は、このようなルールに従っていない NSControl のサブクラスです)。 図 5-1 ターゲット/アクションメカニズムの仕組み メニュー項目は、このようなコントロール/セルアーキテクチャの例外です。ユーザがメニュー からある項目を選択すると、ターゲットにアクションが送信されます。それにもかかわらず、 メニュー(NSMenu オブジェクト)とそれらの項目(NSMenuItem オブジェクト)は、構造 上の意味において、コントロールとセルから完全に異なるものです。NSMenuItem クラスは、 それぞれのインスタンスのためにターゲット/アクションメカニズムを実装します。 NSMenuItem オブジェクトは、ターゲットおよびアクションインスタンス変数(および関連し たaccessorメソッド)を保持し、ユーザがターゲットを選択するとアクションメッセージを送 信します。

ターゲット

ターゲットは、アクションメッセージの受信側です。コントロールまたはそのセルが(セルの ほうが頻繁)、アクションメッセージのターゲットをアウトレットとして保持します(「アウ トレット」を参照)。ターゲットは通常、カスタムクラスのいずれかのインスタンスですが、 そのクラスが適切なアクションメソッドを実装していれば、Cocoa オブジェクトでもかまいま せん。 セルまたはコントロールのターゲットアウトレットを nil に設定し、ターゲットオブジェクト

(22)

を実行時に決めることもできます。ターゲットが nil の場合は、NSApplication オブジェク トが、次のような所定の順番で該当する受信側を検索します。 1. キーウインドウの最初のレスポンダから開始し、nextResponder リンクをたどって NSWindow のコンテンツビューまでレスポンダチェーンを上がります。 注意:キーウインドウはアプリケーションのキー押下に応答し、メニューとダイアログ からのメッセージを受信するウインドウです。アプリケーションのメインウインドウは ユーザアクションの主要な対象であり、しばしばキーステータスも保持します。 2. NSWindow オブジェクトを試し、次に NSWindow の委任を試します。 3. メインウインドウがキーウインドウと異なる場合は、メインウインドウの最初のレス ポンダから開始し、メインウインドウのレスポンダチェーンを NSWindow オブジェク トとその委任まで上がります。 4. 次に、NSApplication オブジェクトは自身の応答を試します。応答できない場合 は、自身の委任を試します。そして最後の手段として、NSApp とその委任が受信側にな ります。

アクション

アクションは、コントロールがターゲットに送信するメッセージであり、ターゲットの観点か らは、アクションに応答するために実装しているメソッドです。コントロールまたはそのセル は(セルのほうが頻繁)、アクションを SEL 型のインスタンス変数として保存します。SEL は Objective-C のデータ型で、メッセージのシグネチャ(識別記号)を指定するのに使われま す。アクションメッセージには、単純で識別可能なシグネチャが付いている必要があります。 呼び出されるメソッドは何も返さず、唯一の引数は id 型です。この引数は慣例により、 sender という名前が付いています。以下に、いくつかのアクションメソッドを定義してい る、NSResponder クラスの例を示します。 - (void)capitalizeWord:(id)sender; アクションメソッドは、同等のシグネチャを持っていることもあります。 - (IBAction) deleteRecord:(id)sender; このケースでは、IBAction は戻り値のデータ型を示すものではありません。値は返されませ

(23)

ん。IBAction は、アプリケーションの開発中に、プログラムによって追加されたアクション と、プロジェクト用に定義されたアクションメソッドの内部リストを同期するために、 Interface Builder が認識する型修飾子です。 sender パラメータは通常、アクションメッセージを送信するコントロールを示します(ただ し、実際の送信側によって、別のオブジェクトに置き換えられている場合もあります)。この 背後にある考えは、はがきの返信用住所に似ています。ターゲットは、必要に応じて詳細な情 報を送信側に問い合わせることができます。実際の送信側オブジェクトが別のオブジェクトを 送信側として置き換えていた場合は、そのオブジェクトを同じように扱う必要があります。た とえば、テキストフィールドがあり、ユーザがテキストを入力すると、次のようにターゲット ではアクションメソッドnameEntered:(名前は任意に付けられたものです)が呼び出される とします。 - (void)nameEntered:(id) sender {

NSString *name = [sender stringValue]; if (![name isEqualToString:@""]) {

NSMutableArray *names = [self nameList]; [names addObject:name]; [sender setStringValue:@""]; } } ここでは応答するメソッドはテキストフィールドの内容を抽出し、その文字列をインスタンス 変数としてキャッシュされている配列に追加して、フィールドをクリアします。送信側へのそ の他の問い合わせとしては、NSMatrix オブジェクトに選択されている行を問い合わせる ([sender selectedRow])、NSButton オブジェクトにその状態を問い合わせる ([sender state])、コントロールに対応するセルにそのタグ(任意の識別子)を問い合わ せる([[sender cell] tag])などが考えられます。

Application Kit で定義されたアクション

Application Kit には、アクションメッセージを送信するための NSActionCell を使ったコン トロールが多数含まれているだけでなく、そのクラスの多くでアクションメソッドを定義して います。これらのアクションのいくつかは、Cocoa アプリケーションプロジェクトを作成する ときに、デフォルトのターゲットに接続されます。たとえば、アプリケーションメニューの Quit コマンドは、グローバルなアプリケーションオブジェクト(NSApp)の terminate: メ ソッドに接続されます。

NSResponder クラスも、テキストに関する共通の処理のためのデフォルトのアクションメッ セージ(標準コマンドともいいます)を多数定義しています。これにより、Cocoa のテキスト

(24)

システムは、これらのアクションメッセージをアプリケーションのレスポンダチェーン(階層 構造になっている一連のイベント処理オブジェクト)に送信できます。そこでは、対応するメ ソッドを実装する NSView、NSWindow、または NSApplication オブジェクトによってアク ションメッセージを処理できます。

ターゲットとアクションの設定

セルとコントロールのターゲットとアクションは、プログラムで、または Interface Builder を使って設定できます。ほとんどのデベロッパにとって、たいていの状況で、Interface Builder は望ましいアプローチとなります。Interface Builder を使ってコントロールとター ゲットを設定するときには、画面上での確認、接続のロック、nib ファイルへの接続のアーカ イブができます。手順はシンプルです(開発ツールのマニュアルに詳しく説明されていま す)。 1. カスタムクラスでアクションメソッドを定義します。 2. カスタムクラスのインスタンスを作成します(まだ存在しない場合)。 3. コントロールまたはセルオブジェクト「から」、作成したカスタムクラスのインス タンスを示すアイコン「へ」、接続ラインを Control キーを押しながらドラッグします。

4. インスペクタ(Interface Builder が自動的に表示)の「Connections」パネルでアク ションメソッドを選択し、「Connect」をクリックします。

(25)

図 5-2 Interface Builder におけるターゲットとアクションの設定 アクションがカスタムクラスのスーパークラスまたは既製の Application Kit クラスによって 処理される場合は、最初のステップは省略できます。もちろん、アクションメソッドを自分で 定義する場合は、必ずそれを実装する必要があります。 アクションとターゲットをプログラムで設定するには、次のメソッドを使ってメッセージをコ ントロールまたはセルオブジェクトに送信します。 - (void)setTarget:(id)anObject; - (void)setAction:(SEL)aSelector; 次の例は、これらのメソッドの使い方を示しています。 [aCell setTarget:myController]; [aControl setAction:@selector(deleteRecord:)]; [aMenuItem setAction:@selector(showGuides:)]; ターゲットとアクションをプログラムで設定するのはメリットがあり、実際に、一定の状況で は考えられる唯一のアプローチになることもあります。たとえば、ネットワーク接続の有無や インスペクタウインドウのロードなど、実行時の状況に応じてターゲットやアクションを変化

(26)

させたい場合などが考えられます。別の例として、ポップアップメニューの項目を動的に設定 し、各ポップアップ項目に独自のアクションを持たせたい場合が考えられます。

(27)

キー値コーディング(Key Value Coding)

次のセクションでは、キー値コーディングと、Cocoa プログラミングにおけるこのテクニック の使い方について説明します。 このセクションの内容: キー値コーディングとは? キー値コーディングとテーブルデータ キー値コーディングとスクリプティング

キー値コーディングとは?

キー値コーディングは、オブジェクトのプロパティに間接的に、一定の状況では自動的にアク セスするためのテクニックです。オブジェクトは一般的にモデルオブジェクト、すなわち、ア プリケーションのデータを保持してそのデータを処理するロジックを定義する、モデル/ビュー /コントローラのパラダイムに属する種類のオブジェクトです。(このパラダイムは、「The Model-View-Controller Design Pattern」で詳しく説明されています)。キー値コーディング は、オブジェクトのプロパティの名前(通常はそのインスタンス変数やアクセサメソッド) を、これらのプロパティの値にアクセスするキーとして使うことで機能します。 キー値コーディングは、いくつかのプログラミング状況ではメリットがあります。テーブル ベースのオブジェクト(テーブルビューやアウトラインビューなど)とデータソースを処理す るコードを単純化できます。また、アプリケーションをスクリプタブルにする場合も重要なテ クニックになります。しかし、キー値コーディングのこれらの用途を見る前に、その動作の仕 組みを詳しく見ていきましょう。 キー値コーディングに欠かせないプログラムインタフェースとして、Objective-C の簡易プロ トコルである NSKeyValueCoding で宣言される 2 つのメソッドがあります。1 つは、オブ ジェクトの値にアクセスするための valueForKey: メソッドで、これは指定したキーによって 識別されるプロパティの値を返します。もう 1 つはtakeValue:forKey: メソッドで、これは 指定したキーによって識別されるプロパティの値を設定します。この 2 つのメソッドで、オブ ジェクトのプロパティとスカラ変数のプロパティの取得、設定ができます。インスタンス変数 がスカラ型であるときには自動的に検出し、必要に応じてそれらを NSNumber オブジェクト にラップ(およびラップ解除)します。

(28)

takeValue:forKey: と valueForKey: のデフォルトの実装では、オブジェクトによって標準 的に実装されているアクセサメソッドの使用を試みるか、または適切なアクセサメソッドがな い場合はインスタンス変数に直接アクセスしようとします。使用する特定のアクセサメソッド を探すときには、あらかじめ決まっている次のパターンに従います。 1. キー名に基づいて、パブリックアクセサメソッドを探します。値を設定するときに は、名前が setKey: の形式のメソッドを使用します。Key は、最初の文字を大文字にしたキー の名前です。値を取得する場合は、getKey、isKey、または key という名前のメソッドを使 用します。 2. パブリックアクセサが見つからない場合は、キー名に基づいてインスタンス変数を 検索するか、値を直接設定します。変数は key という名前である必要があります。 3. 最後に、上記の検索がすべて失敗した場合は、キー値の要求を処理する handleQueryWithUnboundKey: またはhandleTakeValue:forUnboundKey: を呼び出し ます。デフォルトの実装では、例外が生成されます。これらのメソッドを、何か別のことを実 行するようにクラスでオーバーライドできます。 NSKeyValueCoding プロトコルの他のメソッドでは、キー値コーディングのメカニズムをさ らに詳細に制御できます。詳細については、「Key Value Coding」のトピックと

NSKeyValueCoding プロトコルのリファレンスを参照してください。

キー値コーディングとテーブルデータ

キー値コーディングの起源はリレーショナルデータベースにあり、このテクノロジの中心的な 概念はテーブルデータです。このようなデータは表形式で存在し、表の各行がモデルオブジェ クト(簡単に言えばレコード)に対応し、各列がそのレコードの属性、またはプロパティに対 応していると考えられます。 テーブルビュー(NSTableView のインスタンス)とアウトラインビュー(NSOutlineView のインスタンス)などの Application Kit オブジェクトは、テーブルデータを視覚的に表現し ます。これらのオブジェクトは、データソースの役割を果たす外部のカスタムオブジェクトを 使い、表示するデータを要求に応じて提供します(「データソース」を参照)。キー値コー ディングは、データソースの実装を単純化する 1 つの手段となります。 テーブルビューとアウトラインビューは、文字列識別子を各列に結び付けます。この識別子を 対応するプロパティと同じ名前にすると、自動的にキー値コーディングメソッドのキーとして 機能します。どのプロパティが要求されているかを判断するために、各識別子を個別に調べる

(29)

必要がありません。列識別子をキーとして使って、valueForKey: と takeValue:forKey: (ユーザがテーブルを直接編集する場合)を呼び出すだけです。 たとえば、データソースメソッド tableView:objectValueForTableColumn:row: (NSTableView クラスで定義)の次の 2 つの実装を比較し、一方が他方に比べてどれだけ単 純か注目してください(Employee オブジェクトは架空のモデルオブジェクトです)。 リスト 2-1 キー値コーディングを使用しないデータソースメソッドの実装 - (id)tableView:(NSTableView *)tv objectValueForTableColumn:(id)column row:(int)row {

Employee *emp = [employees objectAtIndex:row];

if ( [[column identifier] isEqualToString:@”name”] ) { return [emp name];

}

if ( [[column identifier] isEqualToString:@”dept”] ) { return [emp department];

}

if ( [[column identifier] isEqualToString:@”title”] ) { // etc... } // etc... } リスト 2-2 キー値コーディングを使用したデータソースメソッドの実装 - (id)tableView:(NSTableView *)tv objectValueForTableColumn:(id)column row:(int)row {

Employee *emp = [employees objectAtIndex:row]; return [emp valueForKey:[column identifier]]; }

キー値コーディングとスクリプティング

Cocoa のスクリプティングのサポートは、アプリケーションがそのモデルオブジェクトを介し てスクリプティングを容易に実装できるように設計されています。ユーザがアプリケーション 上で AppleScript コマンドを実行する場合は、そのコマンドをアプリケーションのモデルオブ ジェクトに直接送って作業を実行できるようにするのが目的です。 Mac OS X のスクリプティングは、AppleScript コマンドの実行を自動的にサポートできるよ うに、キー値コーディングに強く依存しています。スクリプタブルアプリケーションでは、モ デルオブジェクトは、サポートする一連のキーを定義します。各キーは、モデルオブジェクト が保持している特定のデータを示します。たとえば、スクリプティング関連のキーには、 「words」、「font」、「documents」、「color」があります。キー値コーディングの API は、オブジェクトにそのキーの値を問い合わせ、それらのキーに新しい値を設定する一般的で

(30)

自動的な方法を提供します。 アプリケーションのオブジェクトを設計するのと同じように、モデルオブジェクトにキーの セットを定義し、アクセサメソッドを実装する必要があります。これで、アプリケーションに 適したスクリプトスイートを定義するときに、各スクリプタブルクラスがサポートするキーを 指定できます。キー値コーディングをサポートすると、大量のスクリプティングサポートを 「無償で」手に入れることになります。キーは、リレーショナルデータベースにルーツがある 3 つのカテゴリに分類できます。 ・属性キー(「color」など) ・1 対 1 関係キー(ドキュメントの NSTextStorage オブジェクト) ・1 対多関係キー(アプリケーションのドキュメント) AppleScript では、オブジェクト階層によってアプリケーション内におけるモデルオブジェク トの構造が決まります。ほとんどの AppleScript コマンドは、親となるコンテナから子要素ま で、このオブジェクト階層を下ることによって、アプリケーション内の 1 つまたは複数のオブ ジェクトを指定します。利用可能なプロパティ間の関係は、クラス記述のキー値コーディング を通じて定義できます。 Cocoa のスクリプティングアーキテクチャにおけるキー値コーディングの詳細については、 「Guidelines for Creating Scriptable Applications」を参照してください。

(31)

ドキュメントの改訂履歴

表 RH-1 はこのトピックの改訂履歴についての説明です。 表 RH-1 トピックの改訂履歴 2003 年 5 月 7 日 「オブジェクトとの通信」初版

図 4-1 Interface Builder におけるアウトレットの接続 アプリケーションは、一般に、そのカスタムコントローラオブジェクトとユーザインタフェー ス上のオブジェクトの間のアウトレット接続を設定しますが、これらの接続は、Interface  Builder でインスタンスとして表現できる任意のオブジェクトの間で、たとえ 2 つのカスタム オブジェクトの間でも作成できます。インスタンス変数と同様に、それをクラスに含めること が正しいという根拠が必要になります。オブジェクトのインスタンス変数が多い
図 1-2 委任に関する現実的なシーケンス 委任する側のオブジェクトがメッセージを送信するのは、委任がそのメソッドを実装している 場合に限られるということを強調しておかなければなりません。これを調べるには、最初に、 委任で NSObject メソッドの respondsToSelector: を呼び出します。この事前のチェック が、簡易プロトコルの設計の鍵となります。 委任メッセージの形式 委任メソッドの形式はあらかじめ決められています。委任メソッドは、委任を実行する  Application Kit オブ
図 5-2 Interface Builder におけるターゲットとアクションの設定 アクションがカスタムクラスのスーパークラスまたは既製の Application Kit クラスによって 処理される場合は、最初のステップは省略できます。もちろん、アクションメソッドを自分で 定義する場合は、必ずそれを実装する必要があります。 アクションとターゲットをプログラムで設定するには、次のメソッドを使ってメッセージをコ ントロールまたはセルオブジェクトに送信します。 - (void)setTarget:(id)anO

参照

関連したドキュメント

〜は音調語気詞 の位置 を示す ○は言い切 りを示 す 内 は句 の中のポイ ント〈 〉内は場面... 表6

ダラの全体の数を四一とすることが多い︵表2︶︒アバャーカラグブタ自身は﹃ヴァジュラーヴァリー﹄の中でマ

線遷移をおこすだけでなく、中性子を一つ放出する場合がある。この中性子が遅発中性子で ある。励起状態の Kr-87

つの表が報告されているが︑その表題を示すと次のとおりである︒ 森秀雄 ︵北海道大学 ・当時︶によって発表されている ︒そこでは ︑五

従来から iOS(iPhone など)はアプリケーションでの電話 API(Application Program

つまり、p 型の語が p 型の語を修飾するという関係になっている。しかし、p 型の語同士の Merge

現在、電力広域的運営推進機関 *1 (以下、広域機関) において、系統混雑 *2 が発生

接続対象計画差対応補給電力量は,30分ごとの接続対象電力量がその 30分における接続対象計画電力量を上回る場合に,30分ごとに,次の式