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

< Previous PageNext Page >

グローバルアプリケーションオブジェクト

すべてのCocoaアプリケーションは単一のNSApplicationオブジェクトによって管理されます。通常、このオブジェクトはNSAppという名前のグローバル変数です。このグローバルアプリケーションオブジェクトはNSApplication(またはそのカスタムサブクラス)のシングルトンインスタンスですが、これには、アプリケーションをターゲットとするユーザイベントとシステムイベントを取得し、それらを該当するオブジェクトにディスパッチする、という重要な役割があります。また、アプリケーションのウインドウを管理する役割も担っています。たとえば、ウインドウの現在の状態をキーまたはメインウインドウとして追跡します(“「ウインドウのステータス」”を参照)。

In this section:

メインイベントループ
イベントのディスパッチについて
ウインドウの管理
アップルイベントの処理


メインイベントループ

NSAppによって実行される処理のほとんどはアプリケーションのメインイベントループの中で発生します。メインイベントループはイベントおよび描画サイクルの基礎となるものです。このループの仕組みを理解するために、Cocoaアプリケーションのmainエントリポイントで何が起きるかを考察してみましょう。標準的なXcode Cocoaプロジェクトでは、mainにはNSApplicationMainという関数呼び出しが1つあります。この関数は、3つの重要な処理を以下の順序で実行します。

  1. クラスメソッドsharedApplicationを呼び出して共有アプリケーションオブジェクト(NSApp)を取得する。

  2. アプリケーションのメインnibファイルをメモリにロードする。

  3. アプリケーションを実行する([NSApp  run ])。

これらの処理についてもう少し詳しく調べてみましょう。まず、いくつかの基本的なことがらについて説明します。実行中のアプリケーションは本質的にはプロセスです。各プロセスはメインスレッドを持ち、1つ以上の二次スレッドを持つことがあります。スレッドはそれぞれ、スレッド用に作成された実行ループを持ちます。実行ループは、プロセスへの入力ソースを監視し、入力ソースが処理の準備を完了した時点でプロセスに制御をディスパッチするためのメカニズムです。

sharedApplicationメソッドには、シングルトンインスタンスを保証するということ以外に、ウインドウサーバからのイベントを受信して処理するためのプログラムインフラストラクチャを準備するという重要な役割もあります。グローバルアプリケーションオブジェクトの初期化の中で、NSApplicationは、イベントを受信するためのイベントソースを作成することによって(Machポートとして実装されます)、ウインドウサーバへの接続を確立します。また、アプリケーションのイベントキューも準備します。イベントキューは、イベントソースから送信されたイベントを受信してキューに配置するためのFIFOメカニズムです。最後に、NSApplicationは、イベントソースを入力ソースとして使用し、メイン実行ループ(メインスレッドの実行ループ)を初期化します(Figure 6-2を参照)。


Figure 6-2  イベントソースのあるメインイベントループ

Figure 6-2 イベントソースのあるメインイベントループ

ウインドウサーバは、I/O Kitデバイスドライバからイベントを受信し、それらを該当するプロセスにディスパッチします。プロセスは、実行ループにあるイベントソースからイベントを受信してキューに置きます。

アプリケーションがメインnibファイルをロードすると、ファイル内のオブジェクトと、それらのオブジェクト間の接続が展開されます。メインnibファイルにはアプリケーションメニューが必ず含まれます。また、1つ以上のウインドウオブジェクトが(それらを構成するビューと一緒に)含まれる場合があります。それ以外のnibファイルについても同様に、起動時に展開される場合があります。たとえば、ドキュメントベースのアプリケーションでは、ユーザがFinderの中でファイルをダブルクリックしたときに書類のnibファイルを展開できます。この最初のグラフィカルユーザインターフェイスは、ユーザが(メニュー項目を選ぶなどの)要求を開始するために必要です。そしてその結果、アプリケーションで処理されるイベントが生成されます。

メインイベントループで処理の中心的な役割を果たすのが、NSApplicationrunメソッドです。このメソッドは、最初にアプリケーション用のアップルイベントハンドラを登録します(“「アップルイベントの処理」”を参照)。次に、閉じたwhileループの中で、runはアプリケーションが終了するまで以下を実行します。

  1. 実行ループで保留中となっているウインドウ表示オブザーバに対して、サービスを提供する(Figure 6-3を参照)。この結果、「ダーティ」としてマークされているウインドウ内のリージョンが再描画される。


    Figure 6-3  実行ループオブザーバのあるメインイベントループ

    Figure 6-3 実行ループオブザーバのあるメインイベントループ
  2. イベントキューにある次のイベントを取得する(nextEventMatchingMask:untilDate:inMode:dequeue:)。

  3. イベントを次に処理する必要のあるオブジェクトに、イベントをディスパッチする。ほとんどの場合、これはNSWindowオブジェクト(sendEvent:)である。詳細については、“「イベントのディスパッチについて」”を参照のこと。

    最終的には、多数のオブジェクトがイベントの処理に関与する可能性があり、呼び出しスタックのサイズがかなり大きくなる場合がある。イベントが処理された後、runに制御が戻る。

nextEventMatchingMask:untilDate:inMode:dequeue:メソッドは、メインイベントループにおいて漏斗のような役割を果たします。このメソッドは、イベントキューにイベントがあれば、キューの一番上にあるイベントをフェッチし、その構造をNSEventオブジェクトに変換します。キューにイベントがなければ、メソッドがブロック状態になります。メソッドがブロック状態にある間は、ウインドウサーバからの新しいイベントが処理されてキューに置かれます。新しいイベントの存在によって、nextEventMatchingMask:untilDate:inMode:dequeue:が「呼び起こされ」、キュー内で最初に一致するイベントが返されます。

ウインドウの自動表示機能が有効になっていて、要表示としてマークされているビューがウインドウにある場合は、そのウインドウによってオブザーバ(入力ソース)も実行ループにインストールされます。NSAppによってキュー内の次のイベントが処理される直前に、このオブザーバが作動し、その結果として対応するビューが再描画されます。ウインドウ内容の自動表示の詳細については、“「ウインドウと描画」”を参照してください。

イベントのディスパッチについて

NSAppは、自身のsendEvent:実装の中で、渡されたイベントの種類を調べ、それに応じてイベントをディスパッチします。通常、ディスパッチのターゲットはアプリケーションのウインドウの1つであり、アプリケーションはそのNSWindowオブジェクトのsendEvent:メソッドを呼び出すことによって、イベントを転送します。NSAppでは、主要な入力イベントであるキーイベントとマウスイベントの2種類のイベントについて、該当するウインドウを見つけるために、それぞれ異なるアプローチが使用されます。

ユーザがキーボードのキーを押すと、キーイベントが生成されます。NSAppはこれらのイベントをキーウインドウ(現在キー押下を受け付けているアプリケーションのウインドウ)に転送します(代替キーストロークなど、場合によっては、ディスパッチをせずにアプリケーションでNSKeyDownイベントを特別に処理することもあります)。

ユーザがマウスを使用してウインドウ上のオブジェクト(たとえば、描画プログラムのグラフィカル図形など)をクリックすると、マウスイベントが生成されます。NSAppはこれらのマウスイベントを、そのマウスイベントが発生したウインドウにディスパッチします。

クリックその他の操作の対象となっているオブジェクトがコントロールオブジェクト(ボタンやスライダなど)の場合、そのオブジェクトから、アクションメッセージと呼ばれる追加のメッセージがアプリケーションに送信されます。アクションメッセージによって、NSApplicationsendAction:to:from:メソッドが呼び出されます。メッセージのターゲットが指定されていない場合、このメソッドはアプリケーションのキーウインドウ(および必要ならばメインウインドウ)のレスポンダチェーンで、適切なターゲットを検索します。そして、メッセージをアクションメッセージのターゲットに送信します。

ほかの種類のイベントについては、NSAppsendEvent:で処理します。イベントによってはアプリケーションに固有のもの(アクティブ化や非アクティブ化など)があり、それらはNSApp自身が処理します。あるいは、1つ以上のウインドウに関連するイベントもあります。たとえば、ウインドウが露出された場合や、画面の解像度が変更された場合などです。このようなイベントについては、NSAppは作用を受けるウインドウで該当するメソッドを呼び出します。

参考資料: レスポンダチェーンについては“「レスポンダとレスポンダチェーン」”で説明しています。キーウインドウの詳細については、“「ウインドウのステータス」”を参照してください。NSControlオブジェクト、およびNSControlオブジェクトとNSCellオブジェクトの連携動作の詳細については、“「コントロールとメニュー」”を参照してください。

ウインドウの管理

グローバルアプリケーションオブジェクトの役割の1つは、アプリケーションのウインドウを管理することです。NSAppは以下のウインドウ管理処理を実行します。

そして、“「イベントのディスパッチについて」”で説明したように、NSAppはウインドウ固有のイベントとアクションメッセージを、作用を受けるウインドウにディスパッチします。また、アプリケーションの「ウインドウ」メニューを管理し、モーダルウインドウとパネルを管理します(“「モーダルウインドウ」”を参照)。

ウインドウを見つけやすくするため、アプリケーションオブジェクトはウインドウリストと呼ばれる、ウインドウへの参照を維持します(Figure 6-4を参照)。ウインドウ管理処理によっては(割り当て解除など)、このリストを反復処理するものがあります(ウインドウリストはwindowsNSAppに送信することによっていつでも取得できます)。また、アプリケーションオブジェクトはウインドウを検索する際、windowWithWindowNumber:呼び出しの中で現在のNSEventオブジェクトから取得したウインドウ番号も使用します。


Figure 6-4  アプリケーションのウインドウリスト

Figure 6-4 アプリケーションのウインドウリスト

注: NSAppは、画面上のウインドウの重なり(Z軸順)に関しては何もしません。Z軸順はウインドウサーバによって管理されます。ウインドウのZ軸順の詳細については、“「ウインドウのZ軸順とレベル」”を参照してください。

アップルイベントの処理

アプリケーションで処理する必要のあるイベントは、必ずしもそのすべてがイベントキューから取得されるとは限りません。Mac OS Xシステム上の他のプロセス(FinderやLaunch Servicesなど)は、アップルイベントを使用してほかのプロセスとやり取りします。これらのプロセスは、たとえばユーザがFinderウインドウで書類をダブルクリックしたときや、アップルメニューから「システム終了」を選んだためにアプリケーションを終了させる必要があるときなどに、アプリケーションに通知を行うために、しばしばアップルイベントを送信します。

Cocoaアプリケーションが起動時に実行する処理の1つとして、いくつかのアップルイベントハンドラの登録があります。アップルイベントがアプリケーションに送信されると、対応するハンドラが呼び出されます。Cocoaアプリケーションは以下のアップルイベント用のハンドラを登録します。

アップルイベントID

説明

kAEOpenApplication

アプリケーションを起動します。

kAEReopenApplication

アプリケーションを再び開きます。たとえば、アプリケーションの実行中にユーザがDockでアプリケーションアイコンをクリックしたときなどに、このイベントが送信されます。

kAEOpenDocuments

開く書類のリストをアプリケーションに提供します。通常は、ユーザがFinderで1つ以上の書類を選択し、書類をダブルクリックしたときに、このイベントが送信されます。

kAEPrintDocuments

プリントする書類のリストをアプリケーションに提供します。通常は、ユーザがFinderで1つまたは複数の書類を選択し、「ファイル」メニューから「プリント」を選んだときに、このイベントが送信されます。

kAEOpenContents

ドラッグされている内容(テキストや画像など)をアプリケーションに提供します。多くの場合、ユーザがDockでアプリケーションのアイコンの上にファイルをドラッグしたときに、このイベントが送信されます。

kAEQuitApplication

アプリケーションに対して終了するよう要求します。

注: この話題の詳細については、『How Cocoa Applications Handle Apple Events』を参照してください。



< 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