App Clipの概要と設定方法

[Configure and link your app clips](https://developer.apple.com/videos/play/wwdc2020/10146/)を見たのでメモです。このセッションには[サンプルコード](https://developer.apple.com/documentation/swiftui/fruta_building_a_feature-rich_app_with_swiftui)もついているので合わせて見ると良いと思います。

※ここに出てくるスクリーンショットは、全て上記の動画のものです。

# 概要

App Clipを使えば、ユーザは簡単かつシームレスにアプリを体験できる。このセッションでは以下のことを説明している。

* App ClipのURLの扱い方
* App Store Connectで設定する方法
* スマートアップバナーを使ってApp Clipを起動する方法
* App ClipをTestFlightで扱う方法

# App Clipの使用例

スムージースタンドでは以下のようなシーンが考えられる。

NFCタグに触れる → 端末の画面下部にスムージー注文用のApp Clipカードが表示される → 開くボタンをタップする → App Clipが起動する → スムージー注文ページに遷移する → Apple Payで購入する → スムージーを受け取る
![スクリーンショット 2020-06-24 10.19.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/5b2aab91-ea39-6ec8-43fe-fbf8b6610f18.png)
このようにNFCタグにApp Clipで使うURL情報を書き込んでおくと、ユーザがタップしたときにNSUserActivityを経由してURL情報が渡され、直接注文ページを開くことができる。

# App Clipの起動方法いろいろ

* NFCタグ：URLが記録されたタグを読み込み
* QRコード：URLが記録されたコードを読み込み
* 地図アプリ：プレースカードのApp Clip URLをタップ
* Siri：位置情報ベースのサジェストをタップ
* Safari：バナーをタップ
* iMessageアプリ：ウェブページのURLを送信したときに表示されるバナーをタップ

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/5f754b86-95cf-6b6c-ef76-c7f03ad96301.png" width="280px"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/9ef57e8c-8c68-989a-4385-ffa22b065a67.png" width="280px"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/6bbe86db-9a2c-9574-34e7-7aba55c47d7b.png" width="280px"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/0190575a-9b9f-414b-b430-75797c208d4c.png" width="280px">

Appleは、App Clip用のビジュアルコードを作成できるツールを今年後半にリリースする予定。

# 設定手順

大きく分けると以下の3つの手順を踏む。

1. Webサーバ上の設定の変更とApp Clipプロジェクトの作成
2. App Clipカードの設定（App Store Connect上でのデフォルト設定）
3. WebページにApp Clipを表示するためのスマートバナーを設定

## Webサーバ側の準備

WebサイトとApp Clipの関連付けは、Universal Links対応のときと同じようにapple-app-site-associationファイルを使う。今回新たにappclipsの項目を追加する。

```json
{
    "appclips": {
        "apps": [ "ABCDE12345.example.fruta.Clip" ]
    },
 
   ...
}
```

## App Clipプロジェクトの準備

Xcodeでプロジェクトの設定に移動し、Signings & Capabilities → Associated DomainsにApp Clipのドメインを追記する。
![スクリーンショット 2020-06-24 17.54.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/3dd6ddb4-6f5b-93f5-232e-6f08478b8f55.png)
App ClipがSwiftUIで作られている場合は、以下のようなコードになる。NSUserActivityからwebpageURLを取得している。

```swift
import SwiftUI

@main
struct AppClip: App {
    var body: some Scene {
        WindowGroup {
           ContentView()
              .onContinueUserActivity(NSUserActivityTypeBrowsingWeb) { userActivity in
                  guard let incomingURL = userActivity.webpageURL,
                        let components = NSURLComponents(url: incomingURL,
                            resolvingAgainstBaseURL: true) 
                  else {
                      return
                  }

                  // Direct to the linked content in your app clip.
              }
        }
    }
}
```

ユーザがApp Clipから普通のアプリにアップグレードした場合、App Clipのリンクを経由するとApp Clipではなくアプリが開かれることになる。そのため、アプリにもユニバーサルリンクを処理するための同様のコードを用意する。

もしApp ClipがUIKitのSceneDelegateライフサイクルを使用している場合、以下のようにハンドリングする。

```swift
// Handle NSUserActivity in UISceneDelegate.

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    func scene(_ scene: UIScene, continue userActivity: NSUserActivity) 
    {
        // Get URL components from the incoming user activity
        guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
            let incomingURL = userActivity.webpageURL,
            let components = NSURLComponents(url: incomingURL, 
                resolvingAgainstBaseURL: true) 
        else {
            return
        }

        // Direct to the linked content in your app clip.
    }

}
```

associated domainを設定してNSUserActivitiesを扱う方法については「What's New in Universal Link」セッションを参照する。

## デバッグ

XcodeでApp Clipを試したいときは、スキームエディタ→Argumentsタブから環境変数を設定する。この状態でRunすると、指定したURLで起動されるようになる。
![スクリーンショット 2020-06-24 19.17.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/99a22f2a-0f0e-2e69-18c7-9e182e67dadd.png)

## App Clipカードの表示要件

App Clipカードに載せるメタデータを考えるときは、以下に従うとより適切な表示ができる。
![スクリーンショット 2020-06-24 19.47.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/1fe04506-0a3c-1c8d-d0c5-af505620b8eb.png)

画像はApp Clipアクションにマッチしたものにすると良い。

## App Store Connectでの設定

アプリとApp Clipの両方を含むビルドをApp Store Connectに送ると、App Store Connect上でApp Clipの設定をするセクションが表示されているはず。ここでデフォルトのApp Clip設定をする。予め定義されたアクションのリストがあるので、それも選択する。
![スクリーンショット 2020-06-24 19.51.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/36815b3a-6c77-71a8-8c80-ecc9852d7df2.png)
Safariやメッセージ以外からもApp Clipにアクセスできるようにしたい場合は、Advanced App Clip ExperiencesセクションのGet Startedをクリックし、高度な設定を行う。この高度な設定をすることでNFCタグやQRコードなどの物理的な方法からも呼び出しが可能になる。

いくつか画面を進めるとこのようなページが表示される。複数のApp Clip Experienceを設定することもできる。
![スクリーンショット 2020-06-24 21.29.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/e34c4819-c15c-d940-d60b-bfd4aec8a5fe.png)
次のページでは画像やタイトルなどを指定する。
![スクリーンショット 2020-06-24 21.36.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/03f1e062-20c1-3ccd-6059-fc81ca03e7e8.png)

## App Clipの複数設定

レストランアプリの場合、注文用App Clip Experience（melamela.example/order）と予約用App Clip Experience（melamela.example/reservation）を設定することもできる。
![スクリーンショット 2020-06-24 21.38.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/3f3b64f5-d549-c13a-f5d4-7b9323e666d2.png)

### ベストプラクティス

App Clipは可能な限り全てのパスを登録する必要はなく、汎用的なプレフィックスを持ったURLを登録すれば良い。

例えば自転車のオンラインレンタル屋さんの場合。
ある自転車を借りるときのURLは `https://bikesrental.example/rent?bikeID=2` になっている。自転車にはそれぞれIDが振られており、予約するときはそのIDを指定する仕様になっている。この場合、App ClipのURLとして登録するのは`https://bikesrental.example/rent`の一つで良い。

次に大手チェーンのカフェ屋さんの場合。
ある店舗のURLは `https://brighteggcafe.example/store/campbell` になっている。全ての店舗で `https://brighteggcafe.example/store/` までは共通なので、このURLを登録すれば良い。

もしこのコーヒーショップのクパチーノ店舗だけ特別なApp Clip体験を提供したい場合は`https://brighteggcafe.example/store/cupertino` を登録し、異なる画像やタイトルを登録すれば良い。

つまり、基本的には全てをカバーする一般的なURLプレフィックスを登録し、異なる体験を提供したいときだけ、より具体的なURLを登録すれば良い。より高度な設定については「What's New in App Store Connect」にて説明される。デザインのベストプラクティスについては「Design Great App Clips」にて。

## Webページでのスマートアプリバナー設定

以下のようなメタタグを書く。iOS 14よりも古いユーザの場合は従来のスマートアプリバナーとして使えるように、app-idも忘れずに指定する。

```html
<meta name="apple-itunes-app" 
    content="app-clip-bundle-id=com.example.fruta.Clip,
    app-id=123456789">
```

バナーの開くボタンをタップすると、デフォルトのApp Clipカードが表示される。もし高度なApp Clip Experience設定をしていたら、その設定に従った表示が出てくる。
![スクリーンショット 2020-06-24 22.24.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/3858ca63-667f-9884-111f-4467bccea045.png)

# デモ

スムージーアプリの実装例はこんなかんじ。
![スクリーンショット 2020-06-24 22.40.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/f977c3ce-f55b-5f1a-d3e4-78e07a23cecc.png)

# Test Flight

アプリとApp Clipの両方を含むビルドをApp Store Connectに配信した後、Test FlightタブからApp Clipセクションを見つけて、「Add App Clip Invocation」をクリックする。タイトルとURLを設定すればTest Flightでテストできるようになる。
![スクリーンショット 2020-06-24 22.55.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/99323817-aca8-8198-2ca4-e010bb68b4a6.png)
App Store Connectでのテストの詳細については「What's New in App Store Connect」にて。