Macintoshには、アプリケーションに関連付けられたドキュメントという概念が常に存在していました。Finderでドキュメントのアイコンをダブルクリックすると、関連付けられたアプリケーションが起動し、そのドキュメントが開きます。この仕組みは長年にわたり改善と改良を重ね、時には洗練され、時にはより粗雑になりました(2009年9月6日の記事「Snow Leopard、ドキュメントクリエーターコードを無視」参照)。しかし、少なくとも簡単で、概ね正常に動作します。
iOS 3.2以降、iPad(そしてiOS 4.0ではiPhoneとiPod touchも)には、ドキュメントの種類とアプリを関連付けるメカニズムが搭載されました。しかし、この2つは比較になりません。Macintoshのメカニズムはロケットのようで、iPhoneのメカニズムは無声映画で羽ばたきながら納屋に激突するおんぼろ車のようです。
iOSにはFinderがなく、ユーザー(少なくともデバイスをジェイルブレイクしていない一般ユーザー)にはファイルシステムが表示されません。そのため、ドキュメントを扱う個々のアプリが、ユーザーに他のアプリでドキュメントを開くオプションを提供する必要があります。ほとんどのiOSアプリは特定のドキュメントタイプに対応していないか、対応していてもこのオプションを提供していません。つまり、それだけです。
アプリがユーザーにそのようなオプションを提供する場合 (Safari やメールなど)、限られた範囲のアクションを実行するためにシステムを呼び出します。システムは、ドキュメントのプレビューを表示したり、[オプション] ダイアログを表示したり、[次のアプリケーションで開く] ダイアログを表示したりできます。これらは、最終的にはほぼ同じになります。たとえば、[オプション] ダイアログでは、ドキュメントを開くアプリの選択肢が 1 つと、[次のアプリケーションで開く] ダイアログを表示するオプションが提供される場合があります。したがって、最終的には、[次のアプリケーションで開く] ダイアログ、つまり問題のドキュメントを開くことができるアプリのリストが表示されます。ユーザーは、リスト内の名前をタップするか、[キャンセル] をタップして何もせずにダイアログを閉じます。
アプリは「開く」ダイアログを表示しておらず、その内容についても何も知らないことに注意してください。このダイアログはシステムに属しています。アプリは、特定の種類のドキュメントを開くことができる他のアプリをシステムに問い合わせる方法がありません。これはiOSの「サンドボックス」ポリシーの一例であると思われます。サンドボックスとは、アプリが厳密に区切られた空間内で動作し、互いの領域に踏み込んだり、互いの領域について知ることさえできないようにするものです。
(ただし、いつものように、Apple 独自のアプリは、他のアプリが取得できないシステム情報にアクセスできる可能性があります。Mobile Safari もこのケースに該当するはずです。なぜなら、このアプリでは [開く] ダイアログが表示されず、独自のインターフェイスを使用しているためです。特定のファイルを開くことができるアプリをシステムに問い合わせる手段がなければ、これは不可能です。)
サンドボックス化の理由から、アプリがドキュメントを探すための中央ドキュメントリポジトリは存在しません。iOSアプリには標準の「開く」ダイアログがありません。iOSには標準の「開く」ダイアログがないため、ファイルシステム全体を閲覧するための組み込み機能が備わっていないのです。アプリはドキュメントを独自のサンドボックス化されたファイルシステム内に保持し、そのファイルシステムを閲覧するための独自のカスタムインターフェースを提供できますが、サンドボックスの外部を参照することはできません。
では、あるアプリは、「次のアプリで開く」ダイアログに応じて、現在別のアプリのサンドボックスにあるドキュメントをどのように開くことができるのでしょうか。それはすべてシステム次第です。アプリは特定の種類のドキュメントを他のどのアプリが開くことができるかを知ることはできませんが、システムは知ることができます。同様に、アプリはドキュメントを自身のサンドボックスから別のアプリのサンドボックスに移動することはできませんが、システムはできます。システムの「次のアプリで開く」ダイアログで、ユーザーが 2 つ目のアプリでドキュメントを開くことを選択した場合、システムが制御します。システムは、2 つ目のアプリのサンドボックス内にある、2 つ目のアプリの受信トレイ フォルダーにドキュメントを配置します。次に、2 つ目のアプリを起動またはフォアグラウンドにして、ドキュメントを新しい場所で開くように要求するメッセージをアプリに送信します。
システムはどのようにして、どのアプリが特定の種類のドキュメントを開くことができるかを認識するのでしょうか?少なくとも、それはMac OS Xと似ています。アプリのバンドルにはInfo.plistと呼ばれるXMLリソースが含まれており、システムはこれを読み取って、アイコンファイルの場所や、どのnibファイルにスタートアップインターフェースが含まれているかなど、アプリに関するさまざまな重要な情報を取得します。Info.plistには、アプリが開くことができるドキュメントの種類もリスト化できます。これらの種類は、Uniform Type Identifier(UTI)によって指定されます。(UTIは、古い4文字のクリエータコードの現代版であり、ファイル拡張子とMIMEタイプのマッピングも可能にします。より詳細な情報については、前述のクリエータコードに関する記事を参照してください。)
パズルのピースを2つ省略しました。実際にはパズルのピースではないからです。まず、iOSデバイスをコンピューターに接続しているときに、iTunesのファイル共有インターフェースを介して一部のアプリにドキュメントをコピーできることはご存知でしょう。これは別のメカニズムです。単純なオンオフスイッチで、ユーザーがiTunesを使ってこのアプリのサンドボックス内の特定のディレクトリにファイルをコピーするか、コピーしないかを切り替えるだけです。
(さらに問題を複雑にしているのは、iBooks は Apple の独自のアプリであるため、当然ながら iTunes と特別な関係があるということだ。iBooks が iTunes Books カテゴリ内のファイルをどのように取得するかについては説明がつかない。)
2つ目に、カスタムURLがあります。アプリは「myScheme://something/or/other」のようなURLスキームを定義でき、WebビューでそのURLがタップされたり、システムに送信されたりすると、アプリに通知が送信されます。ただし、これはドキュメントの種類とは関係ありません。これは、アプリによって定義され、ユーザーまたは他のアプリがその秘密を知っている場合にのみ使用できる、メッセージを送信するための秘密コードのようなものです。そして、アプリがそのようなメッセージを受信したときにどのように応答するかは、完全にアプリ次第です。
要約すると、ドキュメントを任意に選択して、それを開くように何らかのアプリに要求することはできません。ドキュメントを任意に選択することすらできません。ドキュメントに遭遇した何らかのアプリが、それを表示したいと感じた場合のみ、「開く」ダイアログが表示されます。アプリができないのと同じ理由で、特定の種類のファイルを開く準備ができているアプリを簡単に見つけることはできません。アプリバンドルの内部を調べて Info.plist を表示する簡単な方法はなく、アプリ (Apple 独自のアプリを除く) がそのような照会を実行するために使用できるシステムコールはありません。iOS でドキュメントを操作できるようにするプロセス全体は、ミトンと耳あてを着けた人に目隠しをして編み方を教えようとするようなものです。