Apple Developer Connection
Advanced Search
Member Login Log In | Not a Member? Contact ADC

< Previous PageNext Page >

ターゲット/アクションメカニズム

委任、バインディング、通知は、プログラムのオブジェクト間の一定の形式のやり取りを処理するのには役立ちますが、最も頻繁に発生する種類の通信に特に適しているとはいえません。典型的なアプリケーションのユーザインターフェイスは、いくつかのグラフィカルオブジェクトで構成され、その中で最も一般的なオブジェクトはおそらくコントロールでしょう。コントロールは、現実の、または論理上のデバイスをグラフィカルに表現したものです(ボタン、スライダ、チェックボックスなど)。現実のコントロール(ラジオのチューナーなど)と同様に、コントロールを使用して、それが含まれている何らかのシステム(この場合はアプリケーション)に、自分の意図を伝達します。

ユーザインターフェイスにおけるコントロールの役割は単純です。それはユーザの意図を解釈し、他のオブジェクトにその要求を実行するよう指示することです。たとえばユーザがクリックしたり、Returnキーを押したりしてコントロールに働きかけると、ハードウェアデバイスは生のイベントを生成します。コントロールはそのイベントを(Cocoa向けに適切にパッケージ化された状態で)受け取り、それをアプリケーション固有の命令に翻訳します。しかし、イベントだけではユーザの意図に関する十分な情報は得られません。それらは単に、ユーザがマウスボタンをクリックしたり、キーを押したりしたことを伝えるだけだからです。そこで、イベントと命令の間の翻訳を行うために、何らかのメカニズムが必要です。このメカニズムをターゲット/アクションと呼んでいます。

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

In this section:

コントロール、セル、メニュー項目
ターゲット
アクション
Application Kitで定義されているアクション
ターゲットとアクションの設定


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

ほとんどのコントロールは、NSControlクラスを継承するオブジェクトです。コントロールには、アクションメッセージを最初にそのターゲットに送信する役割を担いますが、メッセージを送信するのに必要な情報を持っていることはまれです。このため、多くの場合は、セル(または複数のセル)に頼ることになります。

コントロールはほとんどの場合、1つまたは複数のセル(NSCellから派生したオブジェクト)が関連付けられています。なぜそのような関連付けを行っているのでしょうか?コントロールは、NSViewクラスとNSResponderクラスも含め、その祖先のインスタンス変数の組み合わせをすべて継承しているため、比較的「重い」オブジェクトです。コントロールは高くつくので、画面上でコントロールが占める領域をさまざまな機能分野に分割する目的で、セルが使用されます。セルは軽量のオブジェクトで、コントロールの一部または全部と重なるものと考えることができます。しかし、セルは領域を区切っているだけでなく、役割を分けるものでもあります。セルは本来ならコントロールが実行する描画の一部を実行し、本来ならコントロールが持つデータの一部を保持します。このようなデータの、2つの項目がターゲットとアクションのインスタンス変数です。Figure 5-8に、コントロール/セルのメカニズムを示します。

NSControlNSCellはどちらも抽象クラスであるため、ターゲットとアクションのインスタンス変数の設定を完全には処理できません。デフォルトでは、NSControlは関連したセルがある場合に、単純に情報をそのセルに設定するだけです((NSControlはそれ自身とセル間の1対1のマッピングしかサポートしていませんが、NSMatrixのようなNSControlのサブクラスは複数のセルをサポートしています)。デフォルトの実装では、NSCellは単に例外を引き起こすだけです。ターゲットとアクションの設定処理を実際に実装しているクラス(NSActionCell)を見つけるには、継承チェーンを1つ下る必要があります。

NSActionCellから派生したオブジェクトは、ターゲットとアクションの値をそれらのコントロールに提供することで、そのコントロールがアクションメッセージを作成して適切な送信先に送信できるようにしています。NSActionCellオブジェクトは、マウス(カーソル)の追跡を処理するために領域をハイライトするとともに、指定したターゲットにアクションメッセージを送信するための制御を支援します。ほとんどの場合、NSControlオブジェクトの外観と動作は、対応するNSActionCellオブジェクトに完全に任されます(NSMatrixとそのサブクラスのNSFormは、このようなルールに従っていないNSControlのサブクラスです)。


Figure 5-8  ターゲット/アクションメカニズムの仕組み

Figure 5-8 ターゲット/アクションメカニズムの仕組み

ユーザがメニューからある項目を選択すると、ターゲットにアクションが送信されます。それにもかかわらず、メニュー(NSMenuオブジェクト)とそれらの項目(NSMenuItemオブジェクト)は、構造上の意味において、コントロールとセルから完全に異なるものです。NSMenuItemクラスは、それぞれのインスタンスのためにターゲット/アクションメカニズムを実装し、NSMenuItemオブジェクトは、ターゲットとアクションのインスタンス変数の両方(および関連したアクセサメソッド)を持ち、ユーザがターゲットを選択するとそのターゲットにアクションメッセージを送信します。

注: “「コントロールとメニュー」”で、コントロールセルとメニューのアーキテクチャについてさらに詳しく説明します。『Control and Cell Programming Topics for Cocoa』および『Application Menu and Pop-up List Programming Topics』も参照してください。

ターゲット

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

セルまたはコントロールのターゲットアウトレットを nilに設定し、ターゲットオブジェクトを実行時に決めることもできます。ターゲットがnilの場合は、NSApplicationオブジェクトが、次のような所定の順番で該当する受信側を検索します。

  1. キーウインドウの最初のレスポンダから開始し、nextResponderリンクをたどってNSWindowオブジェクトのコンテンツビューまでレスポンダチェーンを上がります。

    注: キーウインドウはアプリケーションのキー押下に応答し、メニューとダイアログからのメッセージを受信するウインドウです。アプリケーションのメインウインドウはユーザアクションの主要な対象であり、しばしばキーステータスも持っています。

  2. NSWindowオブジェクトを試し、次にウインドウオブジェクトのデリゲートを試します。

  3. メインウインドウがキーウインドウと異なる場合は、メインウインドウの最初のレスポンダから開始し、メインウインドウのレスポンダチェーンをNSWindowオブジェクトとそのデリゲートまで上がります。

  4. 次に、NSApplicationオブジェクトは自身の応答を試します。応答できない場合は、自身のデリゲートを試します。そして最後の手段として、NSAppとそのデリゲートがレシーバになります。

コントロールオブジェクトは、ターゲットを保持しません(保持してはなりません)。ただしアクションメッセージの送信元コントロールのクライアント(通常はアプリケーション)は、そのターゲットがアクションメッセージを受け取るために存在していることを保証する責任があります。これを行うために、ターゲットを保持する必要が生じることがあります。この対策は、デリゲートとデータソースの両方に等しく適用されます。

アクション

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

- (void)capitalizeWord:(id)sender;

アクションメソッドは、同等のシグネチャを持っていることもあります。

- (IBAction) deleteRecord:(id)sender;

このケースでは、IBActionは戻り値のデータ型を示すものではありません。値は返されません。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のテキストシステムは、これらのアクションメッセージをアプリケーションのレスポンダチェーン(階層構造になっている一連のイベント処理オブジェクト)に送信できます。そこでは、対応するメソッドを実装するNSViewNSWindow、またはNSApplicationオブジェクトによってアクションメッセージを処理できます。

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

セルとコントロールのターゲットとアクションは、プログラムで、またはInterface Builderを使って設定できます。ほとんどのデベロッパにとって、たいていの状況で、Interface Builderは望ましいアプローチとなります。Interface Builderを使ってコントロールとターゲットを設定するときには、画面上での確認、接続のロック、nibファイルへの接続のアーカイブができます。手順はシンプルです(開発ツールのマニュアルに詳しく説明されています)。

  1. カスタムクラスでアクションメソッドを定義します。

  2. カスタムクラスのインスタンスを作成します(まだ存在しない場合)。

  3. コントロールまたはセルオブジェクト「から」、作成したカスタムクラスのインスタンスを示すアイコン「へ」、接続ラインをControlキーを押しながらドラッグします。

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


Figure 5-9  Interface Builderにおけるターゲットとアクションの設定

Figure 5-9 Interface Builderにおけるターゲットとアクションの設定

アクションがカスタムクラスのスーパークラスまたは既製のApplication Kitクラスによって処理される場合は、最初のステップは省略できます。もちろん、アクションメソッドを自分で定義する場合は、必ずそれを実装する必要があります。

アクションとターゲットをプログラムで設定するには、次のメソッドを使ってメッセージをコントロールまたはセルオブジェクトに送信します。

- (void)setTarget:(id)anObject;
- (void)setAction:(SEL)aSelector;

次の例は、これらのメソッドの使い方を示しています。

[aCell setTarget:myController];
[aControl setAction:@selector(deleteRecord:)];
[aMenuItem setAction:@selector(showGuides:)];

ターゲットとアクションをプログラムで設定するのはメリットがあり、実際に、一定の状況では考えられる唯一のアプローチになることもあります。たとえば、ネットワーク接続の有無やインスペクタウインドウのロードなど、実行時の状況に応じてターゲットやアクションを変化させたい場合などが考えられます。別の例として、ポップアップメニューの項目を動的に設定し、各ポップアップ項目に独自のアクションを持たせたい場合が考えられます。



< Previous PageNext Page >


Last updated: 2006-05-23




Did this document help you?
Yes: Tell us what works for you.

It’s good, but: Report typos, inaccuracies, and so forth.

It wasn’t helpful: Tell us what would have helped.
Get information on Apple products.
Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Copyright © 2007 Apple Inc.
All rights reserved. | Terms of use | Privacy Notice