> For the complete documentation index, see [llms.txt](https://app.developers.karte.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://app.developers.karte.io/ios-sdk-appendix/appendix-universal-links-ios-sdk.md).

# \[iOS]Universal Links に対応する

KARTE iOS SDKのアプリ内メッセージやプッシュ通知では、標準的な実装を行った時、クリック時の遷移先にリンクを指定すると、 `UIApplication` クラスの `open(_:options:completionHandler:)` を呼び出し外部アプリを起動します。\
`http` または `https` から始まるリンクの場合は Safari等のブラウザが起動します。\
そのため、ボタンのリンク等にアプリ内遷移用の Universal Links を設定していても、標準の挙動ではブラウザアプリを起動してしまいます。

参考：

* [アプリ内メッセージのリンクを制御する | リンククリック時の挙動](https://app.developers.karte.io/ios-sdk-appendix/pages/iyytFunZrCVFzRXz0YRL#リンククリック時の挙動)
* [プッシュ通知を受信する | 通知開封時の処理を実装する](https://app.developers.karte.io/ios-sdk-appendix/pages/F3XEGlW5igUpZFWHqJNM#2-通知開封時の処理を実装する)

KARTEのアクションにおいて Universal Links を利用したアプリ内処理を行いたい場合は、独自にアプリ内処理を実装する必要があります。\
また、アプリがUniversal Linksを受け取った時にKARTE SDKの機能を使用したい場合、アプリのハンドリング実装に加えKARTE SDKのハンドラを呼び出していただく必要があります。

{% hint style="warning" %}
**サンプルコードについて**

サンプルコードはエラーハンドリングなどは、最低限の記述になっています。\
必要であればより厳密な値・型チェックを追加し、リリース前に必ず動作確認をしてください。
{% endhint %}

## アプリ内メッセージのリンクでの対応

アプリ内メッセージ上のリンククリック後、指定したURLを用いてアプリケーション側でUniversal Linksを受け取った時と同等の処理を行いたい場合、`InAppMessagingDelegate` プロトコルの `inAppMessaging(_:shouldOpenURL:onScene:)` を実装し、URLを確認することで処理を行うことができます。\
※ shouldOpenURLはUniversal Linksに限らず、アクション上で発生する全てのリンク遷移のパターンで動作します。

### 実装例

{% tabs %}
{% tab title="Swift" %}
{% code overflow="wrap" %}

```swift
func inAppMessaging(_ inAppMessaging: InAppMessaging, shouldOpenURL url: URL, onScene scene: UIScene) -> Bool {

  // 特定のホスト・パス等でuniversal linksで起動された際と同じ処理を行う
  if url.host == "your-app-domain.example.com" {
    // handleUniversalLinksは、任意のUniversal Linksを処理するアプリ側の処理を想定しています
    handleUniversalLinks(url)
    // SDKの処理を止める場合は `false` を返す
    return false
  }

  // その他のURL等、SDKに移譲する場合は `true` を返す
  return true
}
```

{% endcode %}
{% endtab %}

{% tab title="Objective-C" %}
{% code overflow="wrap" %}

```objc
- (BOOL)inAppMessaging:(KRTInAppMessaging *)inAppMessaging shouldOpenURL:(NSURL *)url onScene:(UIScene *)scene {

    // 特定のホスト・パス等でuniversal linksで起動された際と同じ処理を行う
    if ([url.host isEqualToString:@"your-app-domain.example.com"]) {
        handleUniversalLinks(url);
        // SDKの処理を止める場合は `NO` を返す
        return NO;
    }

    // その他のURL等、SDKに移譲する場合は `YES` を返す
    return YES;
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

また委譲先のインスタンスの登録は、以下のように実装します。

{% tabs %}
{% tab title="Swift" %}
{% code overflow="wrap" %}

```swift
InAppMessaging.shared.delegate = instance
```

{% endcode %}
{% endtab %}

{% tab title="Objective-C" %}
{% code overflow="wrap" %}

```objc
[[KRTInAppMessaging shared] setDelegate:instance];
```

{% endcode %}
{% endtab %}
{% endtabs %}

## プッシュ通知での対応

プッシュ通知をタップした際に、指定したURLを用いてアプリケーション側でUniversal Linksを受け取った時と同等の処理を行いたい場合、通知タップ時のコールバック上でURLを確認することで処理を行うことができます。\
参考：[プッシュ通知を受信する | 通知開封時の処理を実装する](https://app.developers.karte.io/ios-sdk-appendix/pages/F3XEGlW5igUpZFWHqJNM#2-通知開封時の処理を実装する)

### 実装例

#### UserNotifications.frameworkを利用するアプリケーションの場合

{% tabs %}
{% tab title="Swift" %}
{% code overflow="wrap" %}

```swift
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
  let userInfo = response.notification.request.content.userInfo

  // KARTE経由のプッシュ通知であるか判定
  if let notification = RemoteNotification(userInfo: userInfo) {

    // 特定のホスト・パス等でuniversal linksで起動された際と同じ処理を行う
    if url?.host == "your-app-domain.example.com" {
      // handleUniversalLinksは、任意のUniversal Linksを処理するアプリ側の処理を想定しています
      handleUniversalLinks(url)
      completionHandler()
      return
    }

    // その他の場合はSDKの機能を用いて外部アプリを開く
    notification.handle()
  } else {
    // KARTE以外のシステムから送信されたプッシュ通知
  }
  completionHandler()
}
```

{% endcode %}
{% endtab %}

{% tab title="Objective-C" %}
{% code overflow="wrap" %}

```objc
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
  NSDictionary *userInfo = response.notification.request.content.userInfo;

  // KARTE経由のプッシュ通知であるか判定
  KRTRemoteNotification *notification = [[KRTRemoteNotification alloc] initWithUserInfo:userInfo];
  if (notification) {

    // 特定のホスト・パス等でuniversal linksで起動された際と同じ処理を行う
    NSURL *url = [notification url];
    if (url && [url.host isEqualToString:@"your-app-domain.example.com"]) {
        handleUniversalLinks(url);
        completionHandler();
        return;
    }

    // その他の場合はSDKの機能を用いて外部アプリを開く
    [notification handle];
  } else {
    // KARTE以外のシステムから送信されたプッシュ通知
  }
  completionHandler();
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## ディープリンクを利用したKARTE SDK機能

下記のようなディープリンクを利用したKARTE SDKの機能を、カスタムURLスキーム同様にUniversal Links経由でも利用するためには、ディープリンク経由での起動時にSDKのハンドラを呼び出す必要があります。

* ディープリンク経由での起動イベント (`deep_link_app_open`)

参考：[カスタムURLスキームハンドラを追加する](https://app.developers.karte.io/ios-sdk-appendix/pages/GRf2qVego5fENzB8W2cu#カスタムurlスキームハンドラを追加する)

### 実装例

Universal Linksを処理するために、`scene(_:willConnectTo:options:)` および `scene(_:continue:)` メソッド内にハンドラを追加します。

{% tabs %}
{% tab title="Swift" %}
{% code title="SceneDelegate.swift" overflow="wrap" %}

```swift
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
  if let userActivity = connectionOptions.userActivities.first,
     userActivity.activityType == NSUserActivityTypeBrowsingWeb,
     let url = userActivity.webpageURL {
    KarteApp.application(UIApplication.shared, open: url)
  }
}

func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
  if userActivity.activityType == NSUserActivityTypeBrowsingWeb,
     let url = userActivity.webpageURL {
    KarteApp.application(UIApplication.shared, open: url)
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="Objective-C" %}
{% code title="SceneDelegate.m" overflow="wrap" %}

```objc
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
  NSUserActivity *userActivity = connectionOptions.userActivities.anyObject;
  if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb] && userActivity.webpageURL) {
    NSURL *url = [userActivity webpageURL];
    [KRTApp application:[UIApplication sharedApplication] openURL:url];
  }
}

- (void)scene:(UIScene *)scene
continueUserActivity:(NSUserActivity *)userActivity {
  if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb] && userActivity.webpageURL) {
    NSURL *url = [userActivity webpageURL];
    [KRTApp application:[UIApplication sharedApplication] openURL:url];
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

ただし、Scene-based lifecycleを使用していないアプリでは、`application(_:continue:restorationHandler:)` メソッド内にハンドラを追加します。

{% tabs %}
{% tab title="Swift" %}
{% code title="AppDelegate.swift" overflow="wrap" %}

```swift
func application(_ app: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
  if userActivity.activityType == NSUserActivityTypeBrowsingWeb,
     let url = userActivity.webpageURL {
    KarteApp.application(app, open: url)
  }

  // 必要に応じた値を返してください
  return true
}
```

{% endcode %}
{% endtab %}

{% tab title="Objective-C" %}
{% code title="AppDelegate.m" overflow="wrap" %}

```objc
- (BOOL)application:(UIApplication *)app continueUserActivity:(NSUserActivity *)userActivity
 restorationHandler:(void (^)(NSArray *restorableObjects))restorationHandler {
  if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb] && userActivity.webpageURL) {
    NSURL *url = [userActivity webpageURL];
    [KRTApp application:app openURL:url];
  }

  // 必要に応じた値を返してください
  return YES;
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

ディープリンク及びUniversal Links処理の実装については公式ドキュメントも参照してください。

* [Defining a custom URL scheme for your app](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app)
* [Supporting Universal Links in Your App | Apple Developer Documentation](https://developer.apple.com/documentation/xcode/supporting-universal-links-in-your-app)
