macOSの文書アプリをリモートでデバッグしていると、ターミナルからアプリを指定すればサンプルファイルを開けるのに、同じファイルをデスクトップでダブルクリックすると別のアプリが起動したり、開くアプリの選択を求められたりすることがあります。前者の成功は、そのアプリにファイルを渡せたことを示すだけで、ファイルの関連付けが正しいことまでは証明しません。原因を調べるには、ファイルタイプの宣言、アプリによる受け取り、デフォルトのアプリで開く動作を別々に検証します。
この記事では、独自の .notejson ファイルを例にします。中身は JSON ですが、拡張子はアプリ固有の文書であることを示します。操作は、ビルド済みで起動できる macOS アプリを使って行ってください。テストファイルには架空のデータだけを入れ、本番の文書は使いません。
拡張子を判定するだけでなく、ファイルタイプを定義する
独自形式には、変わらないタイプ識別子が必要です。この例では、識別子を dev.sample.notejson、拡張子を notejson とし、内容は JSON とします。アプリの設定では、このタイプをエクスポートすることと、アプリがそのタイプを開けることの両方を宣言します。コード内でファイル名の拡張子を判定するだけでは、Finder に関連付けは作られません。
Xcode のアプリターゲットでエクスポートするタイプと Document Types を設定したら、完成したアプリバンドルの Info.plist を確認します。エクスポートするタイプには、タイプ識別子、拡張子、準拠する上位タイプが含まれている必要があります。文書タイプからは、同じ識別子を参照します。サンプルアプリに閲覧機能しかない場合、文書のロールは Viewer に設定し、未実装の編集機能があるように宣言しないでください。
確認するのはビルド後のアプリバンドルです。プロジェクト画面上の設定だけでは、成果物に反映されたとは限りません。
実際の形式が JSON でないなら、例に合わせるためだけに JSON に準拠すると宣言してはいけません。タイプ間の関係は、実際の内容を反映させてください。宣言を変更したらアプリを再ビルドします。古いアプリバンドルは、プロジェクト設定の変更だけでは更新されません。
配布するアプリバンドルの宣言を確認する
まず、今回検証するアプリを固定のパスに置きます。次のコマンドでは /Applications/NoteReader.app を例にしています。実行前に APP を自分のアプリのパスに変更してください。
APP="/Applications/NoteReader.app"
test -d "$APP/Contents" || exit 1
plutil -extract UTExportedTypeDeclarations json -o - "$APP/Contents/Info.plist"
plutil -extract CFBundleDocumentTypes json -o - "$APP/Contents/Info.plist"
最初の出力で dev.sample.notejson と notejson を、次の出力で同じタイプ識別子と文書のロールを確認します。plutil がキーの不存在を報告したら、ダブルクリックのテストへ進む前に、ターゲットの設定とビルド成果物を見直してください。ビルド設定から最終的な設定ファイルを生成するプロジェクトでは、特にバンドル内のファイルを基準に判断します。
リモートの Mac では、検証しているのが今ビルドしたアプリであることも確かめます。同名のアプリがダウンロードフォルダとアプリケーションフォルダの両方に残っていると、ターミナルでパスを指定したテストと、Finder からデフォルトのアプリで開くテストが、別々のコピーを対象にする可能性があります。タイプ宣言を何度も変更するより、アプリバンドルのパスを記録し、今回のテストに使わない古いコピーを移動しておくほうが有効です。
2通りの開き方で問題を切り分ける
一時的なサンプルを作り、まずアプリを明示して開き、次にシステムのデフォルトの選択を試します。
APP="/Applications/NoteReader.app"
CASE="$(mktemp -d)"
printf '{"title":"association-check"}\n' > "$CASE/demo.notejson"
open -a "$APP" "$CASE/demo.notejson"
open "$CASE/demo.notejson"
open -a が成功した場合、指定したアプリにファイルの処理を依頼できたことを意味します。その後、アプリにサンプルの内容が実際に表示されたかを確認してください。ウィンドウが開いただけでは、読み込みが完了したとはいえません。2つ目のコマンドはアプリを指定しないため、デフォルトで開くアプリの選択が適用されます。Finder で同じサンプルをダブルクリックし、どのアプリで開かれるかを確かめる方法もあります。
デフォルトの関連付けは、その Mac にインストール済みのアプリやユーザーの選択に影響されます。そのため、検証記録には「指定したアプリで開いた結果」と「現在のユーザーのデフォルトで開いた結果」を分けて残してください。後者を、すべての Mac で同じ結果になるという結論にしてはいけません。開くアプリの選択画面が表示された場合も、その事実を記録し、自動的な関連付けの成功とは判定しないでください。
症状から原因を絞り、読み込みコードを誤って修正しない
| 観察された現象 | 優先して確認する箇所 |
|---|---|
| アプリバンドルにタイプまたは文書の宣言がない | ターゲットの設定、実際のビルド成果物 |
| アプリを指定しても読み込めない | ファイルの内容、アプリの受け取り処理と解析処理 |
| アプリを指定すれば読めるが、デフォルトでは別のアプリで開く | 現在のユーザーのデフォルトの関連付け、アプリの別コピー |
| アプリは起動するが、空白の文書が表示される | ファイル受け取り後のエラー処理と画面の状態 |
表の後半2つのケースは、特に混同しやすいものです。システムがファイルをアプリに渡しても、サンプルの形式が正しくなければアプリが解析を拒否することがあります。逆に、アプリがファイルを問題なく解析できても、システムがそのアプリをデフォルトで選ぶとは限りません。どの段階で問題が起きているかを確かめてから、該当するコードを修正します。
検証が終わったら一時的なサンプルを削除し、アプリバンドルのパス、タイプ識別子、サンプルの拡張子、2通りの開き方の結果をビルド記録に残します。次に Info.plist や文書の読み込みコードを変更した際も同じ手順で確認すれば、変化が関連付けにあるのかアプリ内部にあるのかを判断できます。「一度ダブルクリックできた」だけで結論を出す必要はありません。
よくある質問
open -aでは開けるのに、ダブルクリックで別のアプリが起動するのはなぜですか?
open -aはアプリを明示的に選ぶため、既定の関連付けを検証できません。アプリ内の型宣言を確認し、-aを付けずに開くかFinderでダブルクリックしてください。
アプリにファイルが渡っても内容を読めない場合は何を調べますか?
関連付けによる受け渡しと内容の解析は別です。実際のファイル形式が宣言に合うかを確認し、アプリの読み込み処理とエラー表示を調べてください。
クラウドMacをワークフローに取り入れる
VPSPushでは、リモート接続できる専有の物理Macをご利用いただけます。ロケーションと契約期間を選び、注文画面で接続情報と最終金額をご確認ください。