コンテンツにスキップ

カスタム URL を使った実装

URLのルール

<アプリのカスタムURIスキーム名>://jp.popinfo.coupon/coupons/?key=<VALUE>&key2=<VALUE2>

下記はcoupon.sampleというカスタムURLスキームを受取り、クーポン一覧画面を表示する場合の例になります。

"coupon.sample://jp.popinfo.coupon/coupons/?uuid=xxx&action=distribute"

設定方法

info.plistを開いて、以下のように「URL types」->「URL Schemes」の項目にカスタムURLスキームを設定してください。
URL identifireは端末内でユニークな識別文字列を設定してください。
URL Schemesは複数指定可能です。ここでは、sample://というカスタムURLスキームを想定して設定します。

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLName</key>
        <string>fanship.coupon.sample</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>coupon.sample</string>
        </array>
    </dict>
</array>

実装方法

rootViewControllerの取得方法

下記のメソッドを利用して取得します。

func getRootViewController() -> UIViewController? {
    if let windowScene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene {
        return windowScene.windows.first(where: { $0.isKeyWindow })?.rootViewController
    }
    return UIApplication.shared.delegate?.window??.rootViewController
}

SceneDelegateを利用する場合

1. カスタムURLスキームを格納する変数を定義

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?
    var customUrl: URL? // カスタムURLスキームを格納する
    ...

2. アプリが閉じている場合、受取ったカスタムURLスキームを格納

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
    guard let _ = (scene as? UIWindowScene) else { return }

    // アプリが閉じている場合、カスタムURLスキームを確認
    customUrl = connectionOptions.urlContexts.first?.url
}

3. シーンがアクティブ状態になった際に限定クーポンを配布して一覧へ画面遷移

func sceneDidBecomeActive(_ scene: UIScene) {
    ...
    // カスタムURLスキームを確認
    guard let url = customUrl else { return }
    customUrl = nil

    guard let userId = PopinfoReceiver.shared.userId else { return }

    let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true)
    // URLからクーポンのuuidを取得
    if let uuid = urlComponents?.queryItems?.first?.value {
        // FanshipCouponClientの初期化
        FanshipCouponClient.sharedInstance().initWithServiceId("your_service_id")
        // 限定クーポンの配布メソッドを呼び出し
        FanshipCouponClient.sharedInstance().distributeCoupon(withUserId: userId, couponUUID: uuid) { response, error in
            Task { @MainActor in
                if let error {
                    // 限定クーポン配布エラー時の処理
                } else if let response {
                    // 限定クーポン配布が成功した場合に、CouponListViewControllerのインスタンスを作成
                    let vc = CouponListViewController(serviceId: "your_service_id", userId: userId, uuid: response.coupon?.uuid)

                    // UINavigationControllerを利用する場合の画面遷移
                    guard let navigation: UINavigationController = getRootViewController() as? UINavigationController else { return }
                    navigation.popToRootViewController(animated: false)
                    navigation.pushViewController(vc, animated: true)
                }
            }
        }
    }
}

4. アプリ内で呼ばれた場合に限定クーポンを配布して一覧へ画面遷移

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    // カスタムURLスキームを確認
    customUrl = URLContexts.first?.url

    // アプリ内で呼ばれた場合の処理
    if Bundle.main.bundleIdentifier == URLContexts.first?.options.sourceApplication {
        guard let url = customUrl else { return }
        customUrl = nil

        guard let userId = PopinfoReceiver.shared.userId else { return }

        let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true)
        // URLからクーポンのuuidを取得
        if let uuid = urlComponents?.queryItems?.first?.value {
            // FanshipCouponClientの初期化
            FanshipCouponClient.sharedInstance().initWithServiceId("your_service_id")
            // 限定クーポンの配布メソッドを呼び出し
            FanshipCouponClient.sharedInstance().distributeCoupon(withUserId: userId, couponUUID: uuid) { response, error in
                Task { @MainActor in
                    if let error {
                        // 限定クーポン配布エラー時の処理
                    } else if let response {
                        // 限定クーポン配布が成功した場合に、CouponListViewControllerのインスタンスを作成
                        let vc = CouponListViewController(serviceId: "your_service_id", userId: userId, uuid: response.coupon?. uuid)

                        // UINavigationControllerを利用する場合の画面遷移
                        guard let navigation: UINavigationController = getRootViewController() as? UINavigationController else { return }
                        navigation.popToRootViewController(animated: false)
                        navigation.pushViewController(vc, animated: true)
                    }
                }
            }
        }
    }
}

SceneDelegateを利用しない場合

AppDelegate内のopen urlメソッドで、URLからアプリを起動した時の処理を追加してください。

func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {

    let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true)
    // URLからクーポンのuuidを取得
    if let uuid = urlComponents?.queryItems?.first?.value {
        // ユーザーIDは FANSHIP SDK から取得できます
        if let userId = PopinfoReceiver.shared.userId {
            // FanshipCouponClientの初期化
            FanshipCouponClient.sharedInstance().initWithServiceId("your_service_id")
            // 限定クーポンの配布メソッドを呼び出し
            FanshipCouponClient.sharedInstance().distributeCoupon(withUserId: userId, couponUUID: uuid) { response, error in
                Task { @MainActor in
                    if let error {
                        // 限定クーポン配布エラー時の処理
                    } else if let response {
                        // 限定クーポン配布が成功した場合に、CouponListViewControllerのインスタンスを作成
                        let vc = CouponListViewController(serviceId: "your_service_id", userId: userId, uuid: response.coupon?. uuid)

                        // UINavigationControllerを利用する場合の画面遷移
                        guard let navigation: UINavigationController = getRootViewController() as? UINavigationController else { return }
                        navigation.popToRootViewController(animated: false)
                        navigation.pushViewController(vc, animated: true)
                    }
                }
            }
        }
    }

    return true
}

実装例

カスタムURLスキームを利用した実装例について紹介します。

  1. クーポン詳細画面を開く(open)
  2. クーポン配布を行った後、クーポン一覧画面へ遷移する(distribute)
  3. クーポン配布を行った後、クーポン詳細画面へ遷移する(openOnDistribution)
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {

    let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true)
    // URLからクーポンのuuidを取得
    if let uuid = urlComponents?.queryItems?.first?.value {
        // URLからクーポンのactionを取得
        if let action = urlComponents?.queryItems?[1].value {
            if action == "distribute" {
                // ユーザーIDは FANSHIP SDK から取得できます
                if let userId = PopinfoReceiver.shared.userId {
                    FanshipCouponClient.sharedInstance().distributeCoupon(withUserId: userId, couponUUID: uuid) { response, error in
                        Task { @MainActor in
                            if let error {
                                // 限定クーポン配布エラー時の処理
                            } else if let response {
                                // 限定クーポン配布が成功した場合に、CouponListViewControllerのインスタンスを作成
                                let vc = CouponListViewController(serviceId: "your_service_id", userId: userId, uuid: response.     coupon?. uuid)

                                // UINavigationControllerを利用する場合の画面遷移
                                guard let navigation: UINavigationController = getRootViewController() as? UINavigationController else { return }
                                navigation.popToRootViewController(animated: false)
                                navigation.pushViewController(vc, animated: true)
                            }
                        }
                    }
                }
            } else if action == "open" {
                // クーポン一覧から該当クーポンを検索
                searchCoupon(page: page, uuid: uuid)
            } else if action == "openOnDistribution" {
                // ユーザーIDは FANSHIP SDK から取得できます
                if let userId = PopinfoReceiver.shared.userId {
                    FanshipCouponClient.sharedInstance().distributeCoupon(withUserId: userId, couponUUID: uuid) { response, error in
                        Task { @MainActor in
                            if let error {
                                // 限定クーポン配布エラー時の処理
                            } else if let response {
                                // 限定クーポン配布が成功した場合に、CouponListViewControllerのインスタンスを作成
                                let vc = CouponListViewController(serviceId: "your_service_id", userId: userId, uuid: response.     coupon?. uuid)

                                // UINavigationControllerを利用する場合の画面遷移
                                guard let navigation: UINavigationController = getRootViewController() as? UINavigationController else { return }
                                navigation.popToRootViewController(animated: false)
                                navigation.pushViewController(vc, animated: true)
                            }
                        }
                    }
                }
            }
        }
    }

    return true
}

func searchCoupon(page: Int, uuid: String) {
    if let userId = PopinfoReceiver.shared.userId {
        FanshipCouponClient.sharedInstance().getCouponList(withUserId: userId, sortKey: FanshipCouponSortKey.priority,order: false, page: page, providers: nil) { response, error in
            Task { @MainActor in
                if let error {
                    // エラー処理
                } else if let response {
                    if response.coupons.count != 0 {
                        var shouldContinue: Bool = true
                        for coupon: FanshipCoupon in response.coupons {
                            if !FanshipCouponUtils.isCouponUsed(coupon) && coupon.uuid.hasPrefix(uuid) {
                                // CouponDetailViewControllerのインスタンスを作成
                                let vc = CouponDetailViewController(uuid: coupon.uuid, userId: userId)
                                // UINavigationControllerを利用する場合の画面遷移
                                guard let navigation: UINavigationController = getRootViewController() as? UINavigationController else { return }
                                navigation.popToRootViewController(animated: false)
                                navigation.pushViewController(vc, animated: true)
                                shouldContinue = false
                                self.page = 1
                                break
                            }
                        }
                        if shouldContinue {
                            self.page += 1
                            self.searchCoupon(page: self.page, uuid: uuid)
                        }
                    } else {
                        self.page = 1
                    }
                }
            }
        }
    }
}