|
|
Log In | Not a Member? |
Contact ADC |
| < Previous PageNext Page > |
Model-View-Controllerデザインパターン(MVC)はかなり以前から存在します。MVCのバリエーションの登場は、少なくとも初期のSmalltalkの頃にまでさかのぼります。MVCは、アプリケーションのグローバルなアーキテクチャを対象とし、アプリケーションにおける大まかな役割に従ってオブジェクトを分類するという点では、高次元のパターンといえます。また、複数のより基礎的なパターンで構成されるという点では、複合パターンでもあります。
オブジェクト指向プログラムでは、そのデザインにMVCデザインパターンを応用することによって、いくつかの利点がもたらされます。MVCデザインパターンを応用したプログラムのオブジェクトの多くは再利用性、およびインターフェイス定義の質が高いという傾向があります。また、要件の変化に対するプログラム全体の順応性も高まります。つまり、MVCをベースとしていないプログラムよりも拡張しやすいのです。さらに、Cocoaの数多くの技術やアーキテクチャ(バインディング、ドキュメントアーキテクチャ、スクリプト対応など)はMVCをベースにしており、カスタムオブジェクトは、MVCによって定義されている役割の1つを担うことが求められます。
MVCオブジェクトの役割と関係
Cocoaのコントローラオブジェクトの種類
複合デザインパターンとしてのMVC
MVCアプリケーションのためのデザインガイドライン
CocoaにおけるModel-View-Controller
MVCデザインパターンでは、モデルオブジェクト、ビューオブジェクト、コントローラオブジェクトの3種類のオブジェクトが存在するものとしています。このパターンでは、これらの種類のオブジェクトがアプリケーションの中で果たす役割およびオブジェクトどうしのやり取りの経路が定義されています。アプリケーションを設計する際の重要な手順の1つが、これら3つのグループの1つに該当するオブジェクトを選ぶこと(またはそのオブジェクトのカスタムクラスを作成すること)です。これら3種類のオブジェクトはそれぞれ、抽象的な境界によって分かれており、この境界を越えて互いにやり取りします。
モデルオブジェクトは特別な知識や専門技術を表します。これらのオブジェクトは、アプリケーションのデータを保持し、それらのデータを操作するロジックを定義します。適切に設計されたMVCアプリケーションでは、アプリケーションの重要なデータがすべてモデルオブジェクトにカプセル化されます。アプリケーションの永続状態の一部となるデータはすべて、その永続状態の格納場所(ファイル、データベース、パンチカードなど)に関係なく、アプリケーションにロードされた後は、モデルオブジェクトになければなりません。モデルオブジェクトは特定の問題領域に関係する知識や専門技術を表すため、再利用性が高い傾向があります。
モデルオブジェクトには、その表示や編集に使用されるユーザインターフェイスへの明示的なつながりが存在しないことが理想です。たとえば、住所録などを開発する際に、個人を表すモデルオブジェクトを作成する場合、オブジェクトに誕生日を格納することが考えられます。そのようなデータをPersonというモデルオブジェクトに格納することはよい考えです。しかし、日付の表示方法に関する日付書式文字列その他の情報は、おそらく別の場所に格納したほうがよいでしょう。
実際にはこのような分離は必ずしも最善ではなく、柔軟に考える余地も多少ありますが、一般には、モデルオブジェクトはインターフェイスや表示に関することがらに関与すべきではありません。多少の妥当な例外が考えられる例として、描画アプリケーションがあります。描画アプリケーションには、表示されるグラフィックスを表現するモデルオブジェクトがあります。グラフィックオブジェクトがオブジェクト自身の描画方法を知っていることは理にかなっています。なぜなら、グラフィックオブジェクトの主な存在理由が視覚的な要素を定義することだからです。しかし、このような場合でも、グラフィックオブジェクトは特定のビューの中に自身が存在していることや、そもそもビューの中に存在すること自体を前提とするべきではなく、自身の描画のタイミングを知っている責任も負うべできはありません。それらの表示を必要とするビューオブジェクトに描画を要求されるべきなのです。
ビューオブジェクトは、データの表示方法を認識しています。また、アプリケーションのモデルからのデータをユーザが編集できるようにする場合があります。ビューには、表示対象のデータを格納する役割を持たせるべきではありません(もちろんこれは、表示対象のデータを決して格納することはない、という意味ではありません。ビューはパフォーマンス向上のためにデータをキャッシュしたり、他の同様の技法を使ったりすることができます)。ビューオブジェクトには、モデルオブジェクトの一部のみ、またはモデルオブジェクトの全体、あるいは多数の異なるモデルオブジェクトを、表示する役割を持たせることができます。ビューには多数の異なるバリエーションが存在します。
ビューオブジェクトは再利用や設定が可能に場合が多く、複数のアプリケーションに一貫性を持たせることができます。Cocoaでは、Application Kitに非常に多くのビューオブジェクトが定義されており、その多くはInterface Builderパレットに用意されます。たとえば、Application KitのビューオブジェクトであるNSButtonオブジェクトを再利用することで、アプリケーション内のボタンがほかのCocoaアプリケーションのボタンとまったく同様に動作することが保証され、複数のアプリケーションにわたって外観や動作の一貫性が高いレベルで保たれます。
ビューは、モデルを正確に表示しなければなりません。そのため、通常はモデルに対する変更を知る必要があります。モデルオブジェクトは、特定のビューオブジェクトに結び付くことを避けるべきであるため、変更があったことを知らせる汎用の手段が必要になります。
コントローラオブジェクトは、アプリケーションのビューオブジェクトとモデルオブジェクトとの間の仲介役として機能します。多くの場合、コントローラは、ビューで表示する必要のあるモデルオブジェクトにビューが確実にアクセスできるようにする役割を担い、モデルに加えられた変更をビューが知るための伝達路として動作します。また、コントローラオブジェクトでは、アプリケーションの準備処理や調整処理を実行し、ほかのオブジェクトのライフサイクルを管理することもできます。
Cocoaの典型的なMVCデザインでは、ユーザがビューオブジェクトを通じて値を入力したり選択肢を示したりしたときに、その値や選択肢がコントローラオブジェクトに伝達されます。コントローラオブジェクトでは、たとえばアプリケーション固有の何らかの方法でユーザ入力を解釈した後、その入力に関して何を実行すべきか(“新しい値を追加する”や“現在のレコードを削除する”など)をモデルオブジェクトに指示したり、変更された値をモデルオブジェクトのプロパティの1つ反映させたりします。また、コントローラオブジェクトによっては、同じユーザ入力に応じて、外観や動作の一部を変更するようビューオブジェクトに指示する場合もあります(たとえばボタンを無効にするなど)。逆に、モデルオブジェクトが変更されたとき(新しいデータソースへのアクセスが発生したときなど)、通常はモデルオブジェクトからその変更がコントローラオブジェクトに伝達され、コントローラオブジェクトから1つまたは複数のビューオブジェクトに対して、変更に合わせて表示を更新するよう要求が出されます。
コントローラオブジェクトは、その大まかな種類に応じて、再利用可能であったり、そうでなかったりします。Cocoaにおける各種のコントローラオブジェクトの詳細については、“「Cocoaのコントローラオブジェクトの種類」”を参照してください。
オブジェクトが果たすMVCの役割を結合して、たとえば、オブジェクトにコントローラとビューの両方の役割を担うようにさせる、といったことができます。このようなオブジェクトは、ビュー-コントローラと呼ばれます。同様に、モデル-コントローラオブジェクトも可能です。アプリケーションによっては、そのデザインでこのような役割の結合が許容される場合があります。
モデル-コントローラは、主にモデル層に関与するコントローラです。モデル-コントローラはモデルを“所有”し、モデルの管理とビューオブジェクトとのやり取りを主な役割とします。モデル全体に適用されるアクションメソッドは、通常はモデル-コントローラに実装されます。ドキュメントアーキテクチャではこれらのアクションメソッドがいくつかあらかじめ用意されています。たとえば、ドキュメントアーキテクチャの中核であるNSDocumentオブジェクトは、ファイルの保存に関係するアクションメソッドを自動的に処理します。
ビュー-コントローラは、主にビュー層に関与するコントローラです。ビュー-コントローラはインターフェイス(ビュー)を“所有”し、インターフェイスの管理とモデル-コントローラとのやり取りを主な役割とします。ビューに表示されるデータに関与するアクションメソッドは、通常はビュー-コントローラに実装されます。ビュー-コントローラの例としては、同じくドキュメントアーキテクチャの一部であるNSWindowControllerオブジェクトがあります。
“「MVCアプリケーションのためのデザインガイドライン」”では、MVCの役割が結合されたオブジェクトに関するデザイン上のアドバイスを提供しています。
“「コントローラオブジェクトはモデルをビューに結び付ける」”のセクションでは、コントローラオブジェクトの抽象的な概要を示しましたが、実際にはその全体像ははるかに複雑です。Cocoaには、コントローラオブジェクトとして、大まかに分けて仲介コントローラと調整コントローラの2種類が存在します。これらのコントローラオブジェクトは、それぞれ異なるクラス群に関連付けられており、それぞれが異なる範囲の動作を提供します。
仲介コントローラは、通常はNSControllerクラスを継承するオブジェクトであり、Cocoaバインディング技術で使用されます。仲介コントローラは、ビューオブジェクトとモデルオブジェクトの間でデータの流れを促進します(つまり、仲介役となります)。
通常、仲介コントローラはInterface Builderパレットからドラッグする既製のオブジェクトです。これらのオブジェクトを設定することで、ビューオブジェクトのプロパティとコントローラオブジェクトのプロパティとを結ぶバインディングを確立した後、それらのコントローラプロパティとモデルオブジェクトの特定のプロパティとを結ぶバインディングを確立することができます。結果として、ビューオブジェクトに表示されている値をユーザが変更すると、仲介コントローラを通じて、新しい値がモデルオブジェクトに自動的に伝達されて格納されます。また、モデルのプロパティの値が変更されると、その変更がビューに伝達されて表示に反映されます。抽象クラスNSControllerとその具象サブクラス(NSObjectController、NSArrayController、NSUserDefaultsController、およびNSTreeController)は、変更を確定および破棄する機能や、選択およびプレースホルダ値の管理などの、支援機能を提供します。
調整コントローラは、通常はNSWindowControllerオブジェクト、またはNSDocumentControllerオブジェクト、あるいはNSObjectのカスタムサブクラスのインスタンスです。調整コントローラは、アプリケーションの機能全体またはその一部(nibファイルから展開されるオブジェクトなど)を監視(つまり、調整)する役割を担います。調整コントローラが提供するサービスには次のものがあります。
委任メッセージへの応答と通知の監視
アクションメッセージへの応答
“所有している”オブジェクトのライフサイクルの管理(適切な時点での解放など)
オブジェクト間のつながりの確立やその他の準備処理の実行
NSWindowControllerおよびNSDocumentControllerは、Cocoaにおけるドキュメントベースアプリケーションを対象とするアーキテクチャの一部を構成するクラスです。これらのクラスのインスタンスは、前述のサービスのいくつかに対するデフォルト実装を提供します。それらのサブクラスを作成することでさらにアプリケーション固有の動作を実装できます。NSWindowControllerオブジェクトを使用して、アプリケーション内のウインドウのうちドキュメントアーキテクチャに基づいていないウインドウを管理することさえも可能です。
調整コントローラはしばしば、nibファイルにアーカイブされているオブジェクトを所有します。これらのオブジェクトには仲介コントローラやビューオブジェクトも含まれます。File's Ownerとしての仲介コントローラの詳細については、“「複合デザインパターンとしてのMVC」”を参照してください。
NSObjectのカスタムサブクラスのインスタンスは、調整コントローラとして最適な候補です。この種のコントローラオブジェクトでは、仲介と調整の両方の機能が結合されています。仲介の動作に関しては、これらのコントローラはターゲット/アクションやアウトレット、委任、通知などのメカニズムを利用して、ビューオブジェクトとモデルオブジェクトとの間のデータの流れを促進します。これらのコントローラオブジェクトには“グルーコード”が多数含まれる傾向があります。また、これらのコードは特にアプリケーションに固有のものであるため、アプリケーションの中で再利用度の最も低いオブジェクトになります。
参考資料: コントローラオブジェクトの仲介役としての役割の詳細については、“「Mediator」”デザインパターンを参照してください。Cocoaバインディング技術の詳細については、『Cocoa Bindings Programming Topics』を参照してください。
Model-View-Controllerは、より基本的な複数のデザインパターンで構成されているデザインパターンです。これらの基本的なパターンが連携することで、MVCアプリケーションの特徴である機能の分離や通信経路を定義しています。しかし、従来のMVCの概念において適用される一連の基本パターンは、Cocoaで適用されるものとは異なります。その主な違いは、アプリケーションのコントローラオブジェクトとビューオブジェクトに与えられる役割にあります。
本来の(Smalltalkでの)概念では、MVCは、Composite、Strategy、Observerの各パターンで構成されます。
Composite—アプリケーション内のビューオブジェクトは、実際には、連携して動作する、ネストされたビューの構成(つまり、ビュー階層)です。これらの表示コンポーネントは、ウインドウから、テーブルビューなどの複合ビュー、さらにボタンなどの個々のビューに及びます。ユーザ入力と表示は、構成構造の任意のレベルで発生する可能性があります。
Strategy—コントローラオブジェクトは、1つまたは複数のビューオブジェクトの戦略を実装します。ビューオブジェクトでは、自身の機能を視覚的な側面の管理に限定しています。そしてアプリケーション固有のインターフェイス動作に関する決定をすべてコントローラに委任しています。
Observer—モデルオブジェクトは、アプリケーション内の変化に関心を持っているオブジェクト(通常はビューオブジェクト)に対して、その状態が変わった場合に通知を送ります。
これらのパターンは、Figure 4-4に示すように連携して動作します。ユーザは、構成構造のいずれかのレベルで、ビューを操作します。その結果、イベントが生成されます。コントローラオブジェクトはそのイベントを受信し、アプリケーション固有の方法で解釈します(つまり、戦略を適用します)。この戦略では、モデルオブジェクトの状態を変更するための要求を(メッセージを通じて)行ったり、(構成構造のいずれかのレベルに存在する)ビューオブジェクトに対してその動作や外観を変更するよう要求したりできます。これらの要求に応答して、モデルオブジェクトは、オブザーバとして登録されているすべてのオブジェクトに対して、自身の状態が変更されたことを通知します。オブザーバがビューオブジェクトの場合は、その外観を必要に応じて更新する場合もあります。
Cocoaの場合における複合パターンとしてのMVCも、従来の場合といくつかの類似点があり、実際、Figure 4-4の図に基づいて動作するアプリケーションを構築することもまったく可能です。バインディング技術を使用することで、ビューからモデルオブジェクトを直接監視し、状態変更の通知を受信する、CocoaのMVCアプリケーションを簡単に作成できます。ただし、このデザインには理論上の問題があります。ビューオブジェクトとモデルオブジェクトは、アプリケーションの中で再利用性の最も高いオブジェクトであるはずです。ビューオブジェクトは、オペレーティングシステムと、そのシステムでサポートされるアプリケーションの、いわば“ルックアンドフィール”を表しています。外観と動作の一貫性は重要であり、そのためには再利用性の高いオブジェクトが必要になります。モデルオブジェクトは、その定義上、問題領域に関連するデータをカプセル化し、そのデータを対象に操作を実行します。デザインの面では、再利用性を高めるために、モデルオブジェクトとビューオブジェクトは互いに切り離しておくのが最善です。
ほとんどのCocoaアプリケーションでは、モデルオブジェクトにおける状態変更の通知はコントローラオブジェクトを通じてビューオブジェクトに伝達されます。Figure 4-5はこの別の構成を示します。基本的なデザインパターンがさらに2つ関与しているにもかかわらず、ずっと明快です。
この複合デザインパターンにおけるコントローラオブジェクトには、StrategyパターンだけでなくMediatorパターンも組み込まれています。このコントローラオブジェクトは、モデルオブジェクトとビューオブジェクトとの間の双方向のデータの流れを仲介します。モデルの状態の変更は、アプリケーションのコントローラオブジェクトを通じてビューオブジェクトに伝達されます。また、ビューオブジェクトには、ターゲット/アクションメカニズムの実装を通じて、Commandパターンも組み込まれています。
注: ビューオブジェクトからユーザの入力や選択肢を伝達できるようにするターゲット/アクションメカニズムは、調整と仲介の両方のコントローラオブジェクトに実装できます。ただし、メカニズムのデザインはそれぞれの種類のコントローラで異なります。調整コントローラの場合、Interface Builderでビューオブジェクトをそのターゲット(コントローラオブジェクト)につなぎ、特定のシグネチャに準拠する必要のあるアクションセレクタを指定します。調整コントローラは、ウインドウおよびグローバルアプリケーションオブジェクトのデリゲートであるため、レスポンダチェーンの中に置くこともできます。仲介コントローラで使用されるバインディングメカニズムもまた、ビューオブジェクトをターゲットにつなげ、任意の数の任意の型の引数を持つアクションシグネチャを使用できます。ただし、仲介コントローラはレスポンダチェーンの中に置かれることはありません。
Figure 4-5に示した改正版の複合デザインパターンを使用する理由としては、特にMediatorデザインパターンの場合において、理論上の理由だけでなく実用上の理由もあります。仲介コントローラはNSControllerの具象サブクラスから派生され、それらのクラスは、Mediatorパターンの実装以外に、アプリケーションで利用すべき機能(選択やプレースホルダ値の管理など)を数多く提供します。仮にバインディング技術を使用しないことを選択した場合、ビューオブジェクトではCocoaの通知センターなどのメカニズムを使用して、モデルオブジェクトから通知を受信することも可能です。しかし、そのためにはカスタムビューサブクラスを作成し、モデルオブジェクトによってポストされる通知を受け取る手段を追加しなければならなくなります。
適切に設計されたCocoaのMVCアプリケーションでは、多くの場合、調整コントローラが仲介コントローラを“所有”します(仲介コントローラはnibファイルにアーカイブされます)。Figure 4-6は、2種類のコントローラオブジェクトの関係を示します。
次のガイドラインは、アプリケーションのデザインにおけるModel-View-Controllerにかかわる事項に適用されます。
NSObjectのカスタムサブクラスのインスタンスを仲介コントローラとして使用することは可能ですが、そのために必要なすべての作業をこなすべき理由はありません。代わりに、Cocoaバインディング技術用に設計された既製のNSControllerオブジェクトの1つを使用してください。つまり、NSObjectController、NSArrayController、NSUserDefaultsController、またはNSTreeControllerのインスタンスを使用するか、NSControllerの具象サブクラスの1つのカスタムサブクラスを使用してください。
ただし、アプリケーションが非常にシンプルで、アウトレットとターゲット/アクションを使用した仲介動作を実装するのに必要な“グルーコード”を記述したほうが作業がしやすいという場合には、NSObjectのカスタムサブクラスのインスタンスを仲介コントローラとして使用するのは自由です。NSObjectのカスタムサブクラスでは、キー値コーディング、キー値監視、およびエディタプロトコルを使用して、NSControllerの感覚で仲介コントローラを実装することもできます。
MVCの役割を1つのオブジェクトに結合することも可能ですが、全体的な戦略としては、役割を互いに分離しておくのが最善です。そうすることで、オブジェクトの再利用性が高まり、それらが使用されるプログラムの拡張性も高まります。MVCの役割を1つのクラスに結合する場合は、そのクラスにおける支配的な役割を選び、それから(保守の目的で)同じ実装ファイルの中でカテゴリを使用して、ほかの役割を果たすようにクラスを拡張してください。
MVCアプリケーションを適切に設計するためには、できるだけ多くの(少なくとも理論上)再利用が可能なオブジェクトを使用することを目標にしてください。特に、ビューオブジェクトとモデルオブジェクトについて、再利用性を高めてください(既製の仲介コントローラオブジェクトは当然ながら再利用が可能です)。アプリケーション固有の動作は多くの場合、可能な限りコントローラオブジェクトに集約します。
ビューからモデルを直接監視して状態の変更を検出することも可能ですが、そのようにすることはお勧めできません。ビューオブジェクトでモデルオブジェクトの変更に関する情報を取得したい場合は、必ず仲介コントローラオブジェクトを経由するようにしてください。これには2つの理由があります。
バインディングメカニズムを使用して、ビューオブジェクトからモデルオブジェクトのプロパティを直接監視する場合、NSControllerやそのサブクラスがアプリケーションに対して提供する利点(選択やプレースホルダの管理、変更の確定および破棄の機能など)がすべて失われます。
バインディングメカニズムを使用しない場合は、既存のビュークラスをサブクラス化して、モデルオブジェクトによってポストされる変更通知を監視する機能を追加する必要があります。
アプリケーションのクラスがコードレベルで互いに依存関係することがないように努めてください。クラスどうしの依存関係が強いほど、再利用性は低くなります。具体的な推奨事項は、関与する2つのクラスがMVCのどの役割を担うかに応じて異なります。
ビュークラスは、モデルクラスに依存しないようにします(ただし、カスタムビューによっては依存が避けられない場合もあります)。
ビュークラスは、仲介コントローラクラスに依存しないようにします。
モデルクラスは、ほかのモデルクラス以外のクラスに依存しないようにします。
仲介コントローラクラスは、モデルクラスに依存しないようにします(ただし、ビューと同様に、カスタムコントローラクラスの場合は依存が必要になる場合もあります)。
仲介コントローラクラスは、ビュークラスおよび調整コントローラクラスに依存しないようにします。
調整コントローラクラスは、MVCのすべての役割に依存します。
MVCの役割を特定の種類のオブジェクトに割り当てるアーキテクチャがCocoaによって提供されている場合は、そのアーキテクチャを使用してください。そのようにすることで、プロジェクトがずっとまとめやすくなります。たとえば、ドキュメントアーキテクチャには、NSDocumentオブジェクト(nibコントローラ単位のモデル)がFile's Ownerとしてあらかじめ設定されているXcodeプロジェクトテンプレートが含まれています。
Model-View-Controllerデザインパターンは、Cocoaの数多くのメカニズムや技術の基礎になっています。したがって、オブジェクト指向のデザインにおいてMVCを使用することの重要性は、アプリケーションの再利用性および拡張性を高めることだけにとどまりません。MVCに基づくCocoa技術をアプリケーションに組み込む場合、その設計もMVCのパターンに従っていれば、アプリケーションの動作が最適になります。アプリケーションのMVCの分離が適切であれば、これらの技術を利用するのは比較的容易になるはずです。逆に分離が適切でなければ、より多くの作業が必要になります。
Cocoaには、Model-View-Controllerに基づく次のアーキテクチャ、メカニズム、および技術が組み込まれています。
ドキュメントアーキテクチャ。このアーキテクチャでは、ドキュメントベースのアプリケーションは、アプリケーション全体を対象としたコントローラオブジェクト(NSDocumentController)、個々のドキュメントウインドウ用のコントローラオブジェクト(NSWindowController)、および、各ドキュメントのコントローラとモデルの役割を結合するオブジェクト(NSDocument)で構成されます。
バインディング。これまで説明してきたように、MVCはCocoaのバインディング技術の中心となるものです。NSController抽象クラスの具象サブクラスが提供する既製のコントローラオブジェクトを設定することで、ビューオブジェクトと、適切に設計されたモデルオブジェクトとの間のバインディングを確立できます。
アプリケーションのスクリプト対応機能。アプリケーションをスクリプト対応にするための設計を行う際には、MVCデザインパターンに従うことだけでなく、アプリケーションのモデルオブジェクトを適切に設計することも必要不可欠です。アプリケーションの状態にアクセスするスクリプトコマンドや、アプリケーションの動作を要求するスクリプトコマンドは、通常はモデルオブジェクトかコントローラオブジェクトに送信します。
Core Data。Core Dataフレームワークは、モデルオブジェクトのグラフを管理し、それらのオブジェクトを永続性ストアに保存する(および永続性ストアから取得する)ことによって、オブジェクトの永続性を確保します。Core DataはCocoaバインディング技術と密接に統合しています。MVCおよびオブジェクトモデリングデザインパターンは、Core Dataのアーキテクチャにとって必要不可欠な決定要素です。
取り消し(アンドゥ)。取り消しアーキテクチャでは、モデルオブジェクトが再び中心的な役割を果たします。多くの場合、モデルオブジェクトのプリミティブメソッド(これらはアクセサメソッドの場合が多い)に、アンドゥとリドゥの操作を実装します。また、アクションのビューオブジェクトおよびコントローラオブジェクトがこれらの操作に関与する場合もあります。たとえば、それらのオブジェクトに、アンドゥとリドゥのメニュー項目に対して特定のタイトルを与えさせたり、テキストビューの中で選択の取り消しをさせたりすることが考えられます。
参考資料: 『“Other Cocoa Architectures”』では、ドキュメントアーキテクチャ、アプリケーションのスクリプト対応機能、およびCore Dataの概要について説明しています。また、これらの技術について詳しく説明している文書への相互参照もあります。
| < Previous PageNext Page > |
Last updated: 2006-05-23
|
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 |