# \[iOS]アプリ内メッセージのリンクを制御する

## リンクの制御について

### リンククリック時の挙動

ユーザーがアクション内のリンク（aタグ）をクリックすると、SDKは自動でリンクに指定されているURLを開きます。

この時SDKは、`UIApplication` クラスの `open(_:options:completionHandler:)` メソッドを呼び出しており、実際のリンクの処理はOS側に処理を委譲しています。\
そのため基本的には、`http` または `https` から始まるリンクの場合は Safari等のブラウザが起動し、それ以外のスキームの場合は、スキームに対応するアプリケーションが起動する形となります。

### リンククリック時にアプリケーション側で処理を行う

リンククリック後、アプリケーション側で処理を行いたい場合は、`InAppMessagingDelegate` プロトコルの `inAppMessaging(_:shouldOpenURL:onScene:)` を実装する必要があります。\
※ shouldOpenURLはアクション上で発生する全てのリンク遷移のパターンで動作します。

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

```swift
func inAppMessaging(_ inAppMessaging: InAppMessaging, shouldOpenURL url: URL, onScene scene: UIScene) -> Bool {
  // アプリケーション側で独自の処理を行う

  // SDKデフォルトの処理を行わない場合は `false` を返す
  return false
}
```

{% endcode %}
{% endtab %}

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

```objc
- (BOOL)inAppMessaging:(FIRInAppMessaging *)inAppMessaging shouldOpenURL:(NSURL *)url onScene:(UIScene *)scene {
    // アプリケーション側で独自の処理を行う

    // SDKデフォルトの処理を行わない場合は `NO` を返す
    return NO;
}
```

{% 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 %}

{% hint style="info" %}
**Universal Links を利用してアプリ内に遷移させるには？**

`UIApplication` クラスの `openURL` メソッドは、Universal Links を適切に処理することができないため、そのままでは `Safari` が起動してしまいます。\
そのため Universal Links をリンクとして指定する場合は、アプリケーション側でリンククリック後の処理を実装する必要があります。\
参考：[Universal Links に対応する](/ios-sdk-appendix/appendix-universal-links-ios-sdk.md)
{% endhint %}

## アプリケーション内の特定画面に遷移させる

アプリ内メッセージのリンククリックをトリガーにアプリケーション内の特定画面に遷移させるには、リンクURLとしてディープリンクURLを設定する必要があります。

ディープリンクURLを設定することにより、アプリを起動するところまでは行えますが、特定の画面に遷移させるところまではできません。\
そのため特定の画面に遷移させる処理については、AppDelegateに予め実装しておく必要があります。

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

```swift
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
  // TODO: URLを解析して特定画面に遷移させる処理を実装する必要がある
  return true
}
```

{% endcode %}
{% endtab %}

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

```objc
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
  // TODO: URLを解析して特定画面に遷移させる処理を実装する必要がある
  return YES;
}
```

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

なお iOS13 から利用可能な `UISceneDelegate` を実装している場合は、`scene(_:willConnectTo:options:)` および `scene(_:openURLContexts:)` メソッド内にハンドラを追加します。**UISceneDelegateの設定が有効な場合は上記のUIApplicationDelegateのメソッドは呼ばれません。**

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

```swift
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
  if let context = connectionOptions.urlContexts.first {
	  // TODO: URLを解析して特定画面に遷移させる処理を実装
  }
}

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
  if let context = URLContexts.first {
	  // TODO: URLを解析して特定画面に遷移させる処理を実装
  }
}
```

{% endcode %}
{% endtab %}

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

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

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

{% 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)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://app.developers.karte.io/ios-sdk-appendix/appendix-iam-link-control-ios-sdk.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
