adstage
モバイル SDKディープリンク

iOS

AdStage DeepLink 統合ガイド(iOS)

目次

  1. 概要
  2. プロジェクト設定
  3. Info.plist 設定
  4. AppDelegate 設定
  5. ディープリンク受信処理
  6. ディープリンク生成
  7. 高度な機能
  8. トラブルシューティング

概要

AdStage DeepLink SDK は次の機能を提供します。

  • リアルタイムディープリンク:URL Scheme、Universal Links による即時処理
  • ディファードディープリンク:アプリのインストール後、初回起動時に自動復元
  • 動的ディープリンク生成:サーバー API によるトラッキング可能なリンクの生成
  • アトリビューショントラッキング:UTM パラメータに基づくマーケティング分析

プロジェクト設定

CocoaPods の設定

Podfile

platform :ios, '15.0'
 
target 'YourApp' do
  use_frameworks!
  
  # AdStage SDK
  pod 'AdapterAdStage', '3.0.11'
end
 
post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '15.0'
    end
  end
end

インストール:

pod install

Info.plist 設定

1. URL Scheme の設定

Info.plist に追加:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLName</key>
        <string>com.example.myapp</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>myapp</string>
        </array>
    </dict>
</array>

Info.plist に追加:

<key>com.apple.developer.associated-domains</key>
<array>
    <string>applinks:go.myapp.com</string>
    <string>applinks:go.adstage.net</string>
</array>

Xcode の設定:

  1. Signing & Capabilities タブを選択
  2. + Capability をクリック
  3. Associated Domains を追加
  4. ドメインを追加:
    • applinks:go.myapp.com
    • applinks:go.adstage.net

3. Apple App Site Association ファイル

サーバーに配置:https://go.myapp.com/.well-known/apple-app-site-association

{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appID": "TEAM_ID.com.example.myapp",
        "paths": ["*"]
      }
    ]
  }
}

注意事項:

  • ファイル拡張子なし(.json を付けないこと)
  • Content-Type: application/json
  • HTTPS 必須
  • ルートパスまたは .well-known フォルダに配置

4. 必須の権限設定

<!-- ネットワーク通信 -->
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <false/>
</dict>
 
<!-- バックグラウンドモード(任意) -->
<key>UIBackgroundModes</key>
<array>
    <string>fetch</string>
    <string>remote-notification</string>
</array>

AppDelegate 設定

Swift - AppDelegate.swift

import UIKit
import AdapterAdStage
 
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow?
    
    // MARK: - Application Lifecycle
    
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        
        // 1. AdStage SDK の初期化
        initializeAdStage()
        
        // 2. ディープリンクリスナーの設定
        setupDeepLinkListener()
        
        return true
    }
    
    // MARK: - AdStage Initialization
    
    private func initializeAdStage() {
        AdStageManager.shared.initialize(
            apiKey: "your-api-key-here",
            serverUrl: "https://api.adstage.app"  // 任意
        )
        
        print("✅ AdStage SDK の初期化完了")
    }
    
    private func setupDeepLinkListener() {
        // 統合ディープリンクリスナーの設定
        DeepLinkManager.shared.setDeepLinkListener { [weak self] deepLinkData in
            guard let self = self else { return }
            
            print("""
            📱 ディープリンク受信:
            - Short Path: \(deepLinkData.shortPath)
            - Link ID: \(deepLinkData.linkId)
            - Source: \(deepLinkData.source.description)
            - Parameters: \(deepLinkData.parameters)
            """)
            
            // ディープリンクの処理
            self.handleDeepLink(deepLinkData)
        }
    }
    
    // MARK: - Deep Link Handling
    
    private func handleDeepLink(_ data: DeepLinkData) {
        // ソース別の処理
        switch data.source {
        case .realtime:
            print("🔗 リアルタイムディープリンクの処理")
            handleRealtimeDeepLink(data)
            
        case .install:
            print("📦 ディファードディープリンクの処理(アプリのインストール後の初回起動)")
            handleDeferredDeepLink(data)
            
        case .unknown:
            print("❓ 不明なディープリンクソース")
        }
    }
    
    private func handleRealtimeDeepLink(_ data: DeepLinkData) {
        // パラメータに基づく画面遷移
        if let campaign = data.parameters["campaign"] {
            navigateToCampaign(campaign)
        } else if let promo = data.parameters["promo"] {
            navigateToPromotion(promo)
        } else {
            navigateToHome()
        }
    }
    
    private func handleDeferredDeepLink(_ data: DeepLinkData) {
        // オンボーディング後に処理、または即時処理
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { [weak self] in
            self?.handleRealtimeDeepLink(data)
        }
    }
    
    // MARK: - Navigation
    
    private func navigateToCampaign(_ campaign: String) {
        print("🎯 キャンペーン画面へ遷移: \(campaign)")
        
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            if let campaignVC = storyboard.instantiateViewController(
                withIdentifier: "CampaignViewController"
            ) as? CampaignViewController {
                campaignVC.campaignId = campaign
                
                if let navController = self.window?.rootViewController as? UINavigationController {
                    navController.pushViewController(campaignVC, animated: true)
                }
            }
        }
    }
    
    private func navigateToPromotion(_ promo: String) {
        print("🎁 プロモーションを適用: \(promo)")
        // プロモーション処理ロジック
    }
    
    private func navigateToHome() {
        print("🏠 ホーム画面へ遷移")
        // ホーム画面へ遷移
    }
    
    // MARK: - URL Scheme Deep Link (iOS 8+)
    
    func application(
        _ app: UIApplication,
        open url: URL,
        options: [UIApplication.OpenURLOptionsKey : Any] = [:]
    ) -> Bool {
        
        print("📲 URL Scheme ディープリンク受信: \(url)")
        
        // AdStage で処理
        let handled = DeepLinkManager.shared.handleDeepLink(url)
        
        if handled {
            print("✅ AdStage がディープリンクを処理しました")
            return true
        }
        
        // その他の URL Scheme の処理(例: OAuth コールバック)
        if url.scheme == "myapp" {
            // カスタム処理
            return handleCustomScheme(url)
        }
        
        return false
    }
    
    // MARK: - Universal Links (iOS 9+)
    
    func application(
        _ application: UIApplication,
        continue userActivity: NSUserActivity,
        restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
    ) -> Bool {
        
        // Universal Link かどうかを確認
        guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
              let url = userActivity.webpageURL else {
            return false
        }
        
        print("🌐 Universal Link 受信: \(url)")
        
        // AdStage で処理
        let handled = DeepLinkManager.shared.handleUniversalLink(userActivity)
        
        if handled {
            print("✅ AdStage が Universal Link を処理しました")
            return true
        }
        
        // その他の Universal Link の処理
        return handleCustomUniversalLink(url)
    }
    
    // MARK: - Custom Handlers
    
    private func handleCustomScheme(_ url: URL) -> Bool {
        print("🔧 カスタム URL Scheme の処理: \(url)")
        // OAuth、決済コールバックなどの処理
        return false
    }
    
    private func handleCustomUniversalLink(_ url: URL) -> Bool {
        print("🔧 カスタム Universal Link の処理: \(url)")
        // 一般的な Web リンクの処理
        return false
    }
}

SwiftUI - App 構造

import SwiftUI
import AdapterAdStage
 
@main
struct MyApp: App {
    
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onOpenURL { url in
                    // URL Scheme の処理
                    print("📲 URL 受信: \(url)")
                    _ = DeepLinkManager.shared.handleDeepLink(url)
                }
        }
    }
}
 
class AppDelegate: NSObject, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil
    ) -> Bool {
        
        // AdStage の初期化
        AdStageManager.shared.initialize(
            apiKey: "your-api-key-here",
            serverUrl: "https://api.adstage.app"
        )
        
        // ディープリンクリスナーの設定
        setupDeepLinkListener()
        
        return true
    }
    
    private func setupDeepLinkListener() {
        DeepLinkManager.shared.setDeepLinkListener { deepLinkData in
            print("📱 ディープリンク受信: \(deepLinkData.shortPath)")
            // 処理ロジック
        }
    }
    
    func application(
        _ application: UIApplication,
        continue userActivity: NSUserActivity,
        restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
    ) -> Bool {
        // Universal Link の処理
        return DeepLinkManager.shared.handleUniversalLink(userActivity)
    }
}

ディープリンク受信処理

1. リアルタイムディープリンクの処理

import AdapterAdStage
 
class DeepLinkHandler {
    
    static let shared = DeepLinkHandler()
    
    func setupListener() {
        DeepLinkManager.shared.setDeepLinkListener { [weak self] deepLinkData in
            guard let self = self else { return }
            
            // ディープリンクデータの抽出
            let shortPath = deepLinkData.shortPath
            let parameters = deepLinkData.parameters
            let source = deepLinkData.source
            
            print("""
            ✅ ディープリンク受信完了
            - Short Path: \(shortPath)
            - Link ID: \(deepLinkData.linkId)
            - Source: \(source.description)
            - Event Type: \(deepLinkData.eventType)
            """)
            
            // UTM パラメータの抽出
            let utmParams = deepLinkData.getUtmParameters()
            print("📊 UTM Parameters: \(utmParams)")
            
            // カスタムパラメータの抽出
            let customParams = deepLinkData.getCustomParameters()
            print("🔧 Custom Parameters: \(customParams)")
            
            // ビジネスロジックの処理
            self.processDeepLink(deepLinkData)
        }
    }
    
    private func processDeepLink(_ data: DeepLinkData) {
        // パラメータ別の分岐処理
        if let campaign = data.getParameter("campaign") {
            handleCampaignDeepLink(campaign, data: data)
        } else if let productId = data.getParameter("product_id") {
            handleProductDeepLink(productId, data: data)
        } else if let promo = data.getParameter("promo") {
            handlePromoDeepLink(promo, data: data)
        } else {
            handleDefaultDeepLink(data)
        }
    }
    
    private func handleCampaignDeepLink(_ campaign: String, data: DeepLinkData) {
        print("🎯 キャンペーンディープリンク: \(campaign)")
        
        DispatchQueue.main.async {
            // キャンペーン画面へ遷移
            NotificationCenter.default.post(
                name: .navigateToCampaign,
                object: nil,
                userInfo: ["campaign": campaign, "data": data]
            )
        }
    }
    
    private func handleProductDeepLink(_ productId: String, data: DeepLinkData) {
        print("🛍️ 商品ディープリンク: \(productId)")
        
        DispatchQueue.main.async {
            NotificationCenter.default.post(
                name: .navigateToProduct,
                object: nil,
                userInfo: ["productId": productId]
            )
        }
    }
    
    private func handlePromoDeepLink(_ promo: String, data: DeepLinkData) {
        print("🎁 プロモーションディープリンク: \(promo)")
        
        // プロモーションコードを自動適用
        applyPromoCode(promo)
    }
    
    private func handleDefaultDeepLink(_ data: DeepLinkData) {
        print("📋 デフォルトのディープリンク処理")
        
        DispatchQueue.main.async {
            // ホーム画面へ遷移
            NotificationCenter.default.post(name: .navigateToHome, object: nil)
        }
    }
    
    private func applyPromoCode(_ code: String) {
        // プロモーション適用ロジック
        print("プロモーションコードを適用: \(code)")
    }
}
 
// Notification 名の定義
extension Notification.Name {
    static let navigateToCampaign = Notification.Name("navigateToCampaign")
    static let navigateToProduct = Notification.Name("navigateToProduct")
    static let navigateToHome = Notification.Name("navigateToHome")
}

2. ディファードディープリンク(自動処理)

// ディファードディープリンクは AdStageManager.initialize() の時点で自動的に処理されます。
// 個別の実装は不要です!
 
// 初期化時に自動で:
// 1. デバイスフィンガープリントを収集
// 2. サーバーにマッチングをリクエスト
// 3. 保存されたディープリンクがあれば自動的に onDeepLinkReceived を呼び出し
 
// ディファードディープリンクは手動トリガー API を公開しておらず、initialize() の後に自動で処理されます。
// マッチング結果は、上で登録した setDeepLinkListener のコールバックに渡されます。

3. ソース別の処理

func handleDeepLink(_ data: DeepLinkData) {
    switch data.source {
    case .realtime:
        print("🔗 リアルタイムディープリンク - アプリ実行中に受信")
        // すぐに画面遷移が可能
        navigateImmediately(data)
        
    case .install:
        print("📦 ディファードディープリンク - アプリのインストール後の初回起動")
        // オンボーディング後に処理、または遅延処理
        showOnboardingThenNavigate(data)
        
    case .unknown:
        print("❓ 不明なソース")
        handleAsDefault(data)
    }
}
 
private func showOnboardingThenNavigate(_ data: DeepLinkData) {
    // オンボーディング完了後に処理
    DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { [weak self] in
        self?.navigateImmediately(data)
    }
}

ディープリンク生成

1. Builder パターン

import AdapterAdStage
 
class DeepLinkCreator {
    
    // シンプルなディープリンクの生成
    func createSimpleDeepLink() {
        AdStageManager.shared.createDeepLinkBuilder()
            .setName("夏のプロモーション")
            .setDescription("2024 年夏シーズンのプロモーション")
            .setChannel("google-ads")
            .setCampaign("summer2024")
            .addParameter(key: "promo", value: "SUMMER20")
            .create { [weak self] deepLinkInfo, error in
                if let error = error {
                    print("❌ ディープリンクの生成に失敗: \(error.localizedDescription)")
                    return
                }
                
                guard let info = deepLinkInfo else {
                    print("❌ ディープリンク情報なし")
                    return
                }
                
                print("""
                ✅ ディープリンクの生成完了
                - Short URL: \(info.shortUrl)
                - Short Path: \(info.shortPath)
                - Link ID: \(info.linkId)
                """)
                
                // 生成した URL を共有
                self?.shareDeepLink(info.shortUrl)
            }
    }
    
    // すべてのオプションを含める
    func createFullDeepLink() {
        AdStageManager.shared.createDeepLinkBuilder()
            // 基本情報
            .setName("冬のプロモーション")
            .setDescription("2024-2025 冬シーズンのプロモーション")
            .setShortPath("WINTER24")  // ユーザー指定のパス
            
            // トラッキングパラメータ
            .setChannel("facebook-ads")
            .setSubChannel("instagram")
            .setCampaign("winter2024")
            .setAdGroup("fashion-lovers")
            .setCreative("banner-001")
            .setContent("hero-image")
            .setKeyword("winter-sale")
            
            // Android の設定
            .setAndroidConfig(
                packageName: "com.example.myapp",
                appScheme: "myapp://promo/winter",
                webUrl: "https://example.com/promo/winter"
            )
            
            // iOS の設定
            .setIosConfig(
                appStoreId: "123456789",
                appScheme: "myapp://promo/winter",
                webUrl: "https://example.com/promo/winter"
            )
            
            // Web の設定
            .setWebConfig(webUrl: "https://example.com/promo/winter")
            
            // カスタムパラメータ
            .addParameter(key: "discount", value: "30")
            .addParameter(key: "promoCode", value: "WINTER30")
            .addParameter(key: "validUntil", value: "2025-03-31")
            
            .create { deepLinkInfo, error in
                if let error = error {
                    print("❌ エラー: \(error.localizedDescription)")
                    return
                }
                
                guard let info = deepLinkInfo else { return }
                print("✅ Short URL: \(info.shortUrl)")
            }
    }
    
    // 複数のパラメータを一度に設定
    func createDeepLinkWithMultipleParams() {
        let parameters: [String: String] = [
            "campaign": "spring2024",
            "discount": "15",
            "promoCode": "SPRING15",
            "source": "email"
        ]
        
        AdStageManager.shared.createDeepLinkBuilder()
            .setName("春のプロモーション")
            .setChannel("email-marketing")
            .setParameters(parameters)
            .create { deepLinkInfo, error in
                // 処理
            }
    }
    
    // 共有機能
    private func shareDeepLink(_ url: String) {
        DispatchQueue.main.async {
            let text = """
            🎁 特別プロモーションへのご招待!
            
            このリンクから会員登録すると、5,000 ウォン割引クーポンを差し上げます。
            \(url)
            """
            
            let activityVC = UIActivityViewController(
                activityItems: [text],
                applicationActivities: nil
            )
            
            if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
               let rootVC = windowScene.windows.first?.rootViewController {
                rootVC.present(activityVC, animated: true)
            }
        }
    }
}

2. async/await 方式

class AsyncDeepLinkCreator {
    
    func createDeepLink() async {
        do {
            let builder = AdStageManager.shared.createDeepLinkBuilder()
                .setName("新規会員登録イベント")
                .setChannel("referral")
                .setCampaign("invite-friend")
                .addParameter(key: "referrer", value: "USER123")
                .addParameter(key: "bonus", value: "5000")
            
            let info = try await builder.createAsync()
            
            print("✅ ディープリンクの生成完了: \(info.shortUrl)")
            
            // UI の更新
            await MainActor.run {
                self.updateUI(with: info.shortUrl)
            }
            
        } catch {
            print("❌ ディープリンクの生成に失敗: \(error.localizedDescription)")
            
            await MainActor.run {
                self.showError(error)
            }
        }
    }
    
    @MainActor
    private func updateUI(with url: String) {
        // UI の更新
    }
    
    @MainActor
    private func showError(_ error: Error) {
        // エラーの表示
    }
}

3. Objective-C 互換方式

createDeepLinkBuilder() と DeepLinkBuilder のチェーンメソッド、create(completion:) は すべて @objc として公開されているため、Objective-C でもそのまま使用できます。 シンプルなラッパーを作成し、Short URL の文字列だけをコールバックで受け取るように構成できます。

// Objective-C で使用できるシンプルなラッパー
@objc class ObjCCompatibleDeepLinkCreator: NSObject {
    
    @objc func createSimpleDeepLink(name: String, completion: @escaping (String?, Error?) -> Void) {
        AdStageManager.shared.createDeepLinkBuilder()
            .setName(name)
            .create { info, error in
                completion(info?.shortUrl, error)
            }
    }
    
    @objc func createDeepLinkWithDescription(
        name: String,
        description: String,
        completion: @escaping (String?, Error?) -> Void
    ) {
        AdStageManager.shared.createDeepLinkBuilder()
            .setName(name)
            .setDescription(description)
            .create { info, error in
                completion(info?.shortUrl, error)
            }
    }
}

高度な機能

1. グローバルなユーザー属性の設定

UserAttributes でユーザー情報を設定すると、以降に送信されるイベントに自動的に含まれます。 setUserAttributes(_:) は UserAttributes オブジェクトを引数に取り、すべてのフィールドは任意です。

// ログイン時
func onUserLogin(userProfile: UserProfile) {
    let userAttributes = UserAttributes(
        gender: userProfile.gender,
        country: userProfile.country,
        city: userProfile.city,
        age: "\(userProfile.age)",
        language: Locale.current.languageCode ?? "en"
    )
    AdStageManager.shared.setUserAttributes(userAttributes)
    
    print("✅ ユーザー情報の設定完了")
}
 
// ログアウト時(空の属性でリセット)
func onUserLogout() {
    AdStageManager.shared.setUserAttributes(UserAttributes())
    
    print("🚪 ユーザー情報のリセット")
}

参考:デバイス情報(プラットフォーム、モデル、アプリバージョン、OS バージョン、IDFV/IDFA、ATT ステータスなど)は、 SDK がイベント送信時に自動的に収集して含めるため、別途設定する必要はありません。


トラブルシューティング

チェックリスト:

  • Associated Domains の設定を確認
  • apple-app-site-association ファイルの配置を確認
  • HTTPS を使用しているか確認
  • Team ID と Bundle ID が一致しているか確認

検証方法:

# 1. ファイルにアクセスできるか確認
curl https://go.myapp.com/.well-known/apple-app-site-association
 
# 2. Apple CDN のキャッシュを確認
curl https://app-site-association.cdn-apple.com/a/v1/go.myapp.com

デバッグ:

func application(
    _ application: UIApplication,
    continue userActivity: NSUserActivity,
    restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
    
    print("""
    Universal Link Debug:
    - Activity Type: \(userActivity.activityType)
    - Webpage URL: \(userActivity.webpageURL?.absoluteString ?? "nil")
    - User Info: \(userActivity.userInfo ?? [:])
    """)
    
    return DeepLinkManager.shared.handleUniversalLink(userActivity)
}

2. URL Scheme が動作しない

確認事項:

func application(
    _ app: UIApplication,
    open url: URL,
    options: [UIApplication.OpenURLOptionsKey : Any] = [:]
) -> Bool {
    
    print("""
    URL Scheme Debug:
    - URL: \(url)
    - Scheme: \(url.scheme ?? "nil")
    - Host: \(url.host ?? "nil")
    - Path: \(url.path)
    - Query: \(url.query ?? "nil")
    - Source App: \(options[.sourceApplication] ?? "nil")
    """)
    
    return DeepLinkManager.shared.handleDeepLink(url)
}

3. ディファードディープリンクが動作しない

原因:

  • デバイスフィンガープリントの収集失敗
  • サーバーでのマッチング失敗
  • ネットワーク接続の問題

確認:

// ディファードディープリンクは initialize() の後に自動で処理されます(手動トリガー API はありません)。
// マッチング結果は setDeepLinkListener のコールバックに渡されるため、リスナーでログを確認してください。
AdStageManager.shared.setDeepLinkListener { data in
    print("✅ ディファードディープリンク受信: \(data)")
}

4. アプリがバックグラウンドにあるときにディープリンクを受信できない

SceneDelegate の設定(iOS 13+):

import UIKit
import AdapterAdStage
 
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    
    var window: UIWindow?
    
    func scene(
        _ scene: UIScene,
        willConnectTo session: UISceneSession,
        options connectionOptions: UIScene.ConnectionOptions
    ) {
        guard let _ = (scene as? UIWindowScene) else { return }
        
        // URL Context の処理
        if let urlContext = connectionOptions.urlContexts.first {
            _ = DeepLinkManager.shared.handleDeepLink(urlContext.url)
        }
        
        // User Activity の処理
        if let userActivity = connectionOptions.userActivities.first {
            _ = DeepLinkManager.shared.handleUniversalLink(userActivity)
        }
    }
    
    func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
        if let url = URLContexts.first?.url {
            _ = DeepLinkManager.shared.handleDeepLink(url)
        }
    }
    
    func scene(
        _ scene: UIScene,
        continue userActivity: NSUserActivity
    ) {
        _ = DeepLinkManager.shared.handleUniversalLink(userActivity)
    }
}

5. ビルド設定の確認

Build Settings:

- Deployment Target: iOS 15.0 以上
- Swift Language Version: 5.0 以上
- Enable Bitcode: No(Xcode 14 以降では削除済み)

Info.plist の必須項目:

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>myapp</string>
</array>

テスト方法

1. URL Scheme のテスト

Safari でテスト:

myapp://promo/summer
myapp://promo?campaign=summer&discount=20

ターミナルでテスト:

xcrun simctl openurl booted "myapp://promo/summer"

Safari でテスト:

https://go.myapp.com/ABCDEF

メモ(Notes)アプリでテスト:

  1. メモアプリにリンクを入力
  2. リンクを長押し
  3. 「"[アプリ名]" で開く」を選択

ターミナルでテスト:

xcrun simctl openurl booted "https://go.myapp.com/ABCDEF"

3. ログの確認

// ディープリンク受信の確認
DeepLinkManager.shared.setDeepLinkListener { deepLinkData in
    print("""
    ==========================================
    ディープリンク受信テスト
    ==========================================
    Short Path: \(deepLinkData.shortPath)
    Link ID: \(deepLinkData.linkId)
    Source: \(deepLinkData.source.description)
    Parameters:
    \(deepLinkData.parameters.map { "  - \($0.key): \($0.value)" }.joined(separator: "\n"))
    ==========================================
    """)
}

参考資料


目次