カスタムURLスキームでのアプリ間連携を実装してつまずいた話

トラブルシューティング

Core Hapticsでの触覚フィードバックを実装した後、次は自作の別アプリから今のアプリを直接開けるようにしたいと考え、カスタムURLスキームでのアプリ間連携に挑戦しました。

1. Universal Linksと同じ仕組みだと思っていた

以前Universal Linksでのディープリンクを実装していたため、カスタムURLスキームも似たような設定で使えるものだと思い込んでいました。

myapp://open?id=123

実際にはUniversal Linksがhttpsのドメインと紐付いてサーバー側のファイル設置が必要なのに対し、カスタムURLスキームはmyapp://のような独自のスキームをInfo.plistに登録するだけで済み、サーバー側の準備が一切不要という点で仕組みがまったく異なりました。手軽さの代わりに、ドメインによる検証がない分なりすましのリスクがある点も違いとして理解する必要がありました。

2. スキーム名が他のアプリと衝突する可能性を考えていなかった

適当に短いスキーム名(app://のような一般的な名前)を設定していたところ、動作確認中に別のアプリが同じスキームを登録していて意図しない挙動になる可能性があると気づきました。

発生しうる問題:
同じスキームを複数のアプリが登録していると、どちらが開かれるか保証されない

カスタムURLスキームは早い者勝ちのような仕組みで、複数のアプリが同じスキームを登録していると、どのアプリが開くかはOS側の判断に委ねられ、開発者側でコントロールできません。自分のアプリ名やドメインに紐づいた、できるだけ一意になりそうなスキーム名に変更しました。

3. パラメータの受け取り処理を書き忘れていた

URLスキームで起動すること自体はできたのですが、URLに含めたはずのパラメータ(?id=123の部分)がアプリ側でまったく使われていない状態になっていました。

func application(_ app: UIApplication, open url: URL) -> Bool {
    // URLの受け取り処理
    return true
}

アプリが起動すること自体は確認できていたため満足してしまい、渡ってきたURLからクエリパラメータを解析して該当画面に遷移させる処理を書き忘れていました。「起動できる」ことと「渡したい情報を使って正しい画面を開く」ことは別の実装だと改めて実感しました。

4. アプリがすでに起動中のケースを考慮していなかった

アプリが完全に終了している状態からURLスキームで起動するケースはテストできていたのですが、アプリがバックグラウンドで起動中の状態でリンクを踏んだ場合の動作確認を忘れていました。

見落としていたケース:
起動中のアプリに対してURLスキームでアクセスした場合の遷移処理

起動中のケースでは呼ばれるメソッドが異なり(SceneDelegateの別のコールバック)、これを実装していなかったため、アプリがすでに開いている状態でリンクを踏んでも何も起こらないという不具合がありました。アプリの状態(未起動・バックグラウンド・フォアグラウンド)ごとに、それぞれ動作確認が必要だと学びました。

まとめ

  • カスタムURLスキームはUniversal Linksと違いサーバー側の準備が不要な分、なりすましリスクがあり検証には向かない
  • スキーム名は他アプリと衝突しない、一意になりやすい名前を選ぶ
  • URLで起動できることと、パラメータを解析して正しい画面に遷移させることは別の実装。両方必要
  • アプリの状態(未起動・バックグラウンド・フォアグラウンド)ごとに動作確認を行う

手軽に使える仕組みに見えて、実際にはアプリの状態遷移まで含めて考えないと中途半端な連携になってしまうと痛感した実装でした。


本記事は生成AI(Claude)を活用して執筆・編集しています。内容は実体験に基づき、執筆者本人が確認・監修しています。

コメント

タイトルとURLをコピーしました