App Clipの設計と構築方法

WWDC 2020の[Explore app clips](https://developer.apple.com/videos/play/wwdc2020/10174)を見たのでメモです。

※ここに出てくるスクリーンショットは、全て上記の動画のものです。
※App ClipのHIG概要はこちらから。
https://twitter.com/akatsuki174/status/1276481990313734144

# 概要

App Clipの設計と構築方法、App Clipと普通のアプリとの違いについて。

# App Clipとは何なのか

3つの概念を理解する必要がある。
![スクリーンショット 2020-06-29 8.35.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/d02fda44-eb05-b8fa-1026-2dbd210ccbdd.png)

## アプリ

App Clipはあくまでもアプリの追加機能であり、App Clipを作るにはアプリの存在が必要になる。

## App Clip Experience

iOS 14で開いたときにWebブラウザの代わりにApp Clipで処理されるURLのことで、アプリの新しいエントリーポイントになる。ユニバーサルリンク対応をしたことがある人にとってはプロセスが似ていることに気づくはず。違いとしてはApp Clip URLはapp site associationsファイルで定義されているのではなく、App Store Connectを使用して登録されているということ。experienceの作成とカスタマイズについては「Configure and Link your App Clips」にて。


App Clip Experienceを登録してApp Clipがストアで公開されると、そのURLが開かれたときにApp Clipが表示されるようになる。App ClipはQRコード、NFCタグ、Safariやメッセージのリンク、地図アプリ、Siriからの提案などの様々なところから開くことができる。

App Clipを見つける最良の方法は、今年後半に登場する、Appleがデザインした新しいApp Clipコードを使うこと。これならApp Clipが使えるということがわかりやすい。App ClipコードはNFCと視覚コードの使いやすさを備えており、タップしたりスキャンしたりできる。
![スクリーンショット 2020-06-29 8.52.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/9f2a5c42-6eb2-7dfe-da3c-70a9e1c6f2c1.png)

## App Clip

アプリをインストールしなくても一部アプリの体験ができる。

App Clipを提供するには、Xcodeで2つめのアプリケーションターゲットを作成する必要がある。このターゲットにはApp Clipを動かす上で必要なコードとアセットを含める。App Clipターゲットはアプリのようにビルドされるが、大元のアプリは必要になるし、アプリとApp Clipを別々にアップデートすることはできない。ただし、App Storeで公開されると互いに排他的なものになる。

端末はApp Clip Experienceに遭遇すると、そのアプリをインストールしていない場合はApp Clipがダウンロードされる。インストールされている場合はアプリが開かれる。

# より良いApp Clipのために

App Clipは素早く体験できるところが重要なので、ダウンロード後すぐ起動して使えるように、できるだけ小さいサイズにする必要がある。圧縮後10MB以下である必要がある。

以下の図の四角は画面、線はユーザフローを表している。左側はタブバーなどを表し、右に行くにつれてナビゲーションスタックを使ってゴールに向かうイメージ。アプリはこれでも良いが、App Clipの場合はフローを再考する方が良い。
![スクリーンショット 2020-06-29 15.48.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/8fa8619d-95af-8e4b-fa58-681771782d3d.png)
App Clipの強みを活かせる部分だけを考える。プロフィール画面のような定番の機能はもはや意味をなさないかもしれない。
![スクリーンショット 2020-06-29 15.54.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/bc8861a1-af35-13bb-0924-f352f9393f72.png)

異なる体験には別々のURLを使用する。例えば商品を注文する場合、注文とチェックアウトのexperienceを分けるなど。また、複数の店舗を持っている場合はURLで店舗を特定すれば、店舗の選択画面を表示することなくコンテンツに直行できる。

# デモ

## 使用するアプリ

[Fruta](https://developer.apple.com/documentation/swiftui/fruta_building_a_feature-rich_app_with_swiftui)を例にApp Clipを説明。
Frutaはスムージーメニューの閲覧や注文、ポイント獲得、レシピ検索ができるアプリ。App Clipでは注文体験に重点を置きたいので、メニュータブの機能を搭載させる。

## 実装方法

XcodeでApp Clip用の新しいターゲットを作成する。
![スクリーンショット 2020-06-29 21.34.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/f3078ce4-76ca-fb66-54cd-022a01323e21.png)
FrutaアプリのEmbed in Applicationとして埋め込む。
![スクリーンショット 2020-06-29 21.37.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/06d05dd2-c5e0-ddbe-14b3-bd6abf2284fe.png)
App Clipの名前とBundle Identifierは自動で入力される。

App Clipをビルドしてみると、空っぽのボイラーテンプレートが表示されるだけなので、コード、リソース、必要なdependencyを追加していく。新しくSharedAssetsという名前のアセットカタログを作り、App Clipにも必要なリソースを追加してApp Clipターゲットに入れる。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/b6d1090d-e1c9-c6ab-7a93-7016c3261280.png" width="200px">
必要に応じてAPPCLIPという新しいカスタムフラグを定義して使用する。
![スクリーンショット 2020-06-29 21.57.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/df5c315e-3425-df78-46bd-09720a869b70.png)
最後に、スムージーメニューを表示できるように新しいNavigationViewを作成する。

# 技術的な補足説明

![スクリーンショット 2020-06-29 22.24.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100736/a0ba9fc2-f75f-08af-e69c-41774cb5911d.png)
App Clipが複数のApp Clip Experienceをサポートしている場合は、NSUserActivityのwebpageURLを通じてどのexperienceを処理すべきか判断することができる。

App Clipはextensionと異なり、iOS SDKの任意のAPIを使うことができるため、アプリとApp Clip間のコード共有が簡単。ただし、App Clipからはセンシティブなユーザデータへのアクセスは制限されている。データにアクセスできるかどうかはリクエスト前に確認する。例えばApp Clipの場合HealthKitフレームワークを使用するソースコードは共有することができるが、HKHealthStoreのisHealthDataAvailableは常にfalseを返す。

その他ヒントは「Streamline Your App Clip」セッションを見ると良い。

App Clipからアプリにアップグレードした場合にデータ移行できるAPIも用意している。これは共有データコンテナを使って行われる。

# App Clip開発時の注意点

App Clipは一定期間使われないとApp Clipとそのデータが削除される。App ClipのデータはiOSのバックアップには含まれない。App Clipはプライバシーを重視し、フィットネスなどの機密データへのアクセスを制限している。アプリ側がこのようなタイプのデータを使用している場合、より多くの機能を利用してもらうためにインストールを促すことができる。

App ClipはカスタムURLスキーム、ユニバーサルリンク等に登録することはできない。もしカスタムURLスキームをfederatedサインインサービスのコールバックとして使用している場合は、ASWebAuthenticationSessionを使用する必要がある。

App Clipはコンテンツブロッカーのような拡張機能を含めることはできない。

# App Clipとアプリ

App ClipのQRコードを見つけてスキャンしたとする。アプリがインストールされていない場合はiOS側が自動でApp Clipをダウンロードして起動してくれる。一定期間App Clipが使用されなかったら、iOSはデータコンテナ、及びキーチェーンデータを削除する。ユーザが再度このexperienceを始めた時には、以前と同じように全プロセスを繰り返す。App Clipはデバイスにデータを保存することはできるが、システム判断で削除される可能性があるため、一時的なキャッシュだと思って扱うのが良い。

App Clipユーザがアプリがインストールされたら、iOSはカメラ、マイク、Bluetoothアクセスの認証情報を自動で移行してくれる。他にも移行したいデータがあれば、App Clipの標準コンテナではなく共有データコンテナに保存してデータ移行する。

# 優れたApp Clipを作る優れた技術

* Apple Pay
  * クレジットカードを探すことなく素早く買い物をすることができる
* プッシュ通知
  * スムージーが買えるようになったとき、パーキングメーターの期限が切れたときに通知できる
* SwiftUI
  * 小型で再利用可能なコンポーネントに焦点を当てているため相性が良い
* SKOverlay
  * App Clipを使った後にアプリに誘導するためにオーバーレイ表示をする（詳しくは「What's New in In-App Purchase」セッションにて）
* ASAuthorizationController
  * 購入時のリワードなどのためにユーザをアカウントに紐付けるメリットがある場合に使うと、パスワードベースのアカウントやSign in with Appleベースのアカウントにサインインできる（詳しくは「What's New in Authentication」にて）

# まとめ

* App Clipはアプリをインストールしなくても必要に応じて呼び出すことができる
* アプリがインストールされたらデータの引き継ぎができる
* App Clipはアプリと同じ技術を使って構築されているので、アプリの知識を使うことができる
* App Clipは特定のタスク達成に焦点を当てた直線的な機能
* リワードなどの機能は目標を達成した後の任意のステップとして提示されるべき