UIKitでディープリンクを処理する方法

UIKit でディープリンクを処理するには、主に 2 つのメカニズムがあります:**カスタムURLスキーム** (Custom URL Schemes) と **ユニバーサルリンク** (Universal Links) です。どちらもユーザーをアプリ内の特定のコンテンツに直接ナビゲートさせることができますが、ユニバーサルリンクは、そのシームレスなユーザーエクスペリエンスと優れたフォールバック動作により、一般的に好まれています。

Intermediate

UIKit でディープリンクを処理するには、主に 2 つのメカニズムがあります:カスタムURLスキーム (Custom URL Schemes) と ユニバーサルリンク (Universal Links) です。どちらもユーザーをアプリ内の特定のコンテンツに直接ナビゲートさせることができますが、ユニバーサルリンクは、そのシームレスなユーザーエクスペリエンスと優れたフォールバック動作により、一般的に好まれています。

1. カスタムURLスキーム

カスタムURLスキームを使用すると、アプリのURLに一意のプレフィックス(例:myapp://product/123)を定義できます。ユーザーがこのスキームを持つリンクをタップすると、iOSはアプリを起動します。

設定:

  1. Xcode でURLスキームを登録する:

    • Xcode でプロジェクトを開きます。
    • プロジェクトナビゲーターでプロジェクトを選択し、ターゲットを選択します。
    • 「Info」タブに移動します。
    • 「URL Types」セクションで、「+」ボタンをクリックして新しいURLタイプを追加します。
    • 「Identifier」には、アプリのバンドルID(例:com.yourcompany.yourapp)を使用できます。
    • 「URL Schemes」には、希望するカスタムスキーム(例:myapp)を入力します。
  2. AppDelegate または SceneDelegate で受信したURLを処理する:

    • AppDelegate を使用するアプリの場合(古いアプリまたはScene Delegatesを使用しないアプリ): application(_:open:options:) メソッドを実装します。

      swift func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { // Parse the URL and navigate to the appropriate content print("Received URL: \(url)") handleDeepLink(url) return true }

    • SceneDelegate を使用するアプリの場合(iOS 13 以降): scene(_:openURLContexts:) または scene(_:continue:) を実装します。

      ```swift func scene(_ scene: UIScene, openURLContexts URLContexts: Set) { guard let url = URLContexts.first?.url else { return } print("Received URL: (url)") handleDeepLink(url) }

      // For Universal Links, you'll also use this method func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, let url = userActivity.webpageURL else { return } print("Received Universal Link: (url)") handleDeepLink(url) } ```

2. ユニバーサルリンク

ユニバーサルリンクは、ウェブサイトとアプリの両方で機能する標準のHTTPSリンクです。アプリがインストールされている場合、リンクは直接アプリで開かれます。インストールされていない場合は、Safariで開かれます。これにより、はるかにスムーズなユーザーエクスペリエンスが得られます。

設定:

  1. apple-app-site-association ファイルを作成する:

    • このJSONファイルは、iOSにアプリがどのURLを処理できるかを伝えます。
    • このファイルをウェブサーバーのルートまたは .well-known サブディレクトリ(例:https://yourdomain.com/apple-app-site-association)にホストします。
    • 例: json { "applinks": { "apps": [], "details": [ { "appID": "TEAM_ID.com.yourcompany.yourapp", "paths": [ "/product/*", "/settings/*" ] } ] } } TEAM_IDcom.yourcompany.yourapp を実際の値に置き換えてください。
  2. Xcode で Associated Domains Capability を有効にする:

    • Xcode で、プロジェクトとターゲットを選択します。
    • 「Signing & Capabilities」タブに移動します。
    • 「+ Capability」をクリックし、「Associated Domains」を選択します。
    • アプリが処理する必要のある各ドメインにエントリを追加します。プレフィックスとして applinks: を付けます(例:applinks:yourdomain.com)。
  3. AppDelegate または SceneDelegate で受信した URL を処理する:

    • ユニバーサルリンクは NSUserActivity オブジェクトを使用して処理されます。
    • AppDelegate の場合: application(_:continue:restorationHandler:) を実装します。

      swift func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool { guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, let url = userActivity.webpageURL else { return false } print("Received Universal Link: \(url)") handleDeepLink(url) return true }

    • SceneDelegate の場合: 上記のカスタムURLスキームセクションで示した scene(_:continue:) メソッドを使用します。

3. 一般的なディープリンク処理ロジック (handleDeepLink 関数)

カスタムURLスキームを使用する場合でも、ユニバーサルリンクを使用する場合でも、URLを解析してアプリ内でナビゲートするためのコアロジックは同様です。

func handleDeepLink(_ url: URL) {
    guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false) else {
        return
    }

    // Example: myapp://product/123?color=red
    // Example: https://yourdomain.com/product/123?color=red

    if components.host == "product" {
        // Extract product ID from path components or query parameters
        let productID = components.path.replacingOccurrences(of: "/", with: "")
        let color = components.queryItems?.first(where: { $0.name == "color" })?.value

        // Navigate to product detail screen
        // (e.g., using a UINavigationController or presenting a new view controller)
        if let rootViewController = UIApplication.shared.windows.first?.rootViewController as? UINavigationController {
            let productViewController = ProductDetailViewController() // Your custom VC
            productViewController.productID = productID
            productViewController.selectedColor = color
            rootViewController.pushViewController(productViewController, animated: true)
        }
    } else if components.host == "settings" {
        // Navigate to settings screen
        if let rootViewController = UIApplication.shared.windows.first?.rootViewController as? UINavigationController {
            let settingsViewController = SettingsViewController() // Your custom VC
            rootViewController.pushViewController(settingsViewController, animated: true)
        }
    }
    // Add more conditions for different paths/hosts
}

4. セキュリティに関する考慮事項

ディープリンクは潜在的な攻撃ベクトルとなる可能性があります。常にすべてのURLパラメータを検証し、不正な形式のURLは破棄してください。ディープリンクを通じて利用可能なアクションは、ユーザーデータを危険にさらさないものに限定し、コンテンツを直接削除したり機密情報にアクセスしたりすることを決して許可しないでください。

5. ディープリンクのテスト

ディープリンクは次のようにテストできます: * Safari でカスタムURLスキームを入力する(例:myapp://product/123)。 * ターミナルで xcrun simctl openurl booted <URL> コマンドを使用して、iOSシミュレーターでURLを開く。 * Safari でウェブページからユニバーサルリンクをタップする。