--- lang: ja --- # App Clip という新天地で遭難した話 ###### tags: `iOS` `AppClip` `iOS14` ## 要約 * App Clip 開発においては、Xcodeは最新版を使いましょう。 * App Clip はエンタープライズプログラムに加入したアカウントでは利用できません。 * App Clip 向けのプッシュ通知証明書を作る場合は親Appのプッシュ通知証明書を先に作成しましょう。 * App Clip が利用する SDK 内に `requestAlwaysAuthorization()` の記述が **存在** してはいけません。 <br><br><br> </p> ## あらすじ ### <i class="fa fa-user-circle-o" aria-hidden="true"></i> 背景 筆者は * プログラミング経験3年程度の初級者です。 * iOSアプリ開発の経験はそんなにないです。 * iOSアプリ用SDKの開発なら2年弱ほど経験があります。 ### <i class="fa fa-heartbeat" aria-hidden="true"></i> きっかけ とあるiOSアプリ用SDKについて「AppClip上でも使用できるようにしたい」と相談されました。 ### <i class="fa fa-tasks" aria-hidden="true"></i> やったこと App Clip について、実装方法や挙動について調べ、実際に試してみることにしました。 :::success 公式ドキュメント([App Clips](https://developer.apple.com/documentation/app_clips))の他にも、WWDCのビデオ([Explore App Clips](https://developer.apple.com/videos/play/wwdc2020/10174/))が日本語字幕もあってわかりやすかったです。 ::: ### <i class="fa fa-hand-o-right" aria-hidden="true"></i> 結果 App Clip の仕様把握はとても難航しました。 :::success **App Clip 自体の品質があまり高くない状態[^acbadqual]** だったので調査自体がかなり苦労を伴うものとなりました。 ::: [^acbadqual]: iOS 14.0.1 のころですら、AppClipの起動時に2〜3回に1回の割合でクラッシュする現象が確認できていたほどです。 次のセクションで、印象に残ったトラブルをいくつか紹介します。 <br><br><br> ## App Clip インストール時の理不尽なエラー ### <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> 現象 Xcode12RCの少し前頃だったかと思うのですが、ある既存プロジェクトにApp Clipターゲットを追加し、App Clip をシミュレーターにインストールしようとすると、下記のようなエラーが出て、インストール自体が失敗する事象が続きました。 ```! Application identifier of the parent app, "ABCDEFGH." , is not a prefix of the application identifier of the app clip, "ABCDEFGH.foo.Clip" ``` :::warning 文中の `ABCDEFGH` は Team ID です。 「App Clip の App ID が、親の App ID を前方に含んでいないよ」というメッセージですが、ご覧のように含んでいる(プレフィックスになっている)のがわかります。どういうことでしょうか... ::: ### <i class="fa fa-bug" aria-hidden="true"></i> 原因 既存プロジェクトはCocoaPodsを利用していたのですが、AppClipターゲットを追加した際に **なぜか Pods ディレクトリ以下にファイル一式を展開したらしく** application identifier などを `Pods.xcodeproj/project.pbxproj` から拾って来てしまったのが原因で、 App ID の不整合を起こしていたようでした。 :::warning たまたまプロジェクトディレクトリ全体をXcodeの外から串刺し検索してみようと思い至らなかったら原因は永久にわからなかったかもしれません... Xcode上だとディレクトリ構造が実際の構成とは異なる構成で表示されることもあり、なかなか気づきませんでした。 ::: ### <i class="fa fa-wrench" aria-hidden="true"></i> 対処 `Pods.xcodeproj/project.pbxproj` の `PRODUCT_BUNDLE_IDENTIFIER` を直接修正[^fixappid]したらエラーは出なくなったのですが、そもそもPodsディレクトリ以下に展開されていることが問題なので、これは解決とは言えません。 結局、しばらくして **Xcodeを最新にしたあとにターゲットを追加し直す** ことで、現象が再現しなくなり、最終的な解決となりました。 [^fixappid]: 記述した覚えのない文字列が埋まっていたので `{team_id}.{App Clip の Bundle ID}` の書式になるように修正しました。 :::info プロジェクトの構造によっては起きないようで、現象が発生したケースにおいては、いまだ何が悪かったのか謎のままです... ::: <br><br><br> ## On Demand Install Capable が付与されない ### <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> 現象 実機向けにビルドする場合など、署名が必要な段階で **Provisioning profile ***** doesn't support the On Demand Install Capable capability.** というメッセージが表示され、エラーになりました。 ### <i class="fa fa-bug" aria-hidden="true"></i> 原因 プロジェクトに紐付いた Team ID がエンタープライズプログラムに加入しているのが原因でした。 App Clip はエンタープライズプログラムによる(In House ビルドによる)配布をサポートしていないとのことです。 > <font size="1">https://developer.apple.com/forums/thread/654943?answerId=626595022#626595022</font> > App Clips are unsupported in Enterprise apps. そのため、On Demand Install Capable capability が自動的に付与されなかったと考えられます。 :::danger 2020年9月当時、「エンタープライズプログラムだと利用できない」という情報はApple公式のドキュメント類には記載されていませんでした[^epapnf]。 ::: [^epapnf]: 探し方が悪いだけで実はあったのかもしれませんが...私は未だにフォーラム以外では見つけられてないです。 ### <i class="fa fa-wrench" aria-hidden="true"></i> 対処 新しく、エンタープライズプログラムに加入していない Apple アカウントを用意しました。 :::info 支払いが発生するので、現場によっては判子リレーが発生する大変面倒な作業ではないでしょうか... ::: <br><br><br> ## App Clip 用のプッシュ通知証明書が異常な状態で生成される ### <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> 現象 App Clip にプッシュ通知を送るために、Apple Developer サイトからプッシュ通知証明書を生成したところ、異常な状態で出力されました。 具体的には friendlyName が 本来なら **Apple Push Service** となるところ(画像右側)、実際には **Apple Distribution: xxx...** のような文字列(画像左側)になっていました。 :::warning friendlyName が Apple Push Service 始まりの書式でない場合、多くのサードパーティプッシュ配信サービスにおいて証明書(PKCS#12ファイル)の登録に失敗する可能性があります。 ::: ![img](https://pbs.twimg.com/media/ElUqgmEU0AE1igd?format=png&name=900x900) ### <i class="fa fa-bug" aria-hidden="true"></i> 原因 App Clip 向けのプッシュ通知証明書を、親Appのプッシュ通知証明書よりも先に作成したのが原因のようでした。 :::warning 私には不具合にしか見えなかったのですが、もしかしたらこういう仕様にならざるをえない理由があるのかもしれません。 ::: ### <i class="fa fa-wrench" aria-hidden="true"></i> 対処 親Appのプッシュ通知証明書を作成したあとにApp Clip 向けのプッシュ通知証明書を作成したところ、現象は発生しなくなりました。 :::info 「今どきプッシュ通知はみんなp8鍵使ってるから」みたいな理由で確認が後回しにされた感がなくはないです... ::: <br><br><br> ## ITMS-90842: Invalid SDK usage が報告される ### <i class="fa fa-exclamation-triangle" aria-hidden="true"></i> 現象 位置情報を利用するSDKを App Clip に組み込み、親App と一緒に App Store に提出したところ、**デリバリが<font color=red>成功したあと</font>に**、処理中の状態だった App が消失する現象が起きました。 不審に思いメールボックスを確認すると、App Store から「ITMS-90842: Invalid SDK usage」が発生した旨のメールが届いていました。 つまり、App Store 上で ITMS-90842 を理由に App が消去された、ということでした。 ### <i class="fa fa-bug" aria-hidden="true"></i> 原因 SDK内部に `-[CLLocationManager requestAlwaysAuthorization]` の記述が存在していたこと原因でした。 一応、SDKの中では「App Clip 上で起動した場合は `-[CLLocationManager requestAlwaysAuthorization]` をコールしない」ように実装していたのですが、どうやらコールしないようにするだけでは駄目だったようで[^notcallwontwork]、 **`-[CLLocationManager requestAlwaysAuthorization]` の<font color=red>記述そのものが存在してはならない</font>** ようでした。 [^notcallwontwork]: `-[CLLocationManager requestAlwaysAuthorization]` を[到達不能コード](https://ja.wikipedia.org/wiki/%E5%88%B0%E9%81%94%E4%B8%8D%E8%83%BD%E3%82%B3%E3%83%BC%E3%83%89)にした状態でSDKをビルドし、アプリに実装して確認しましたが、 ITMS-90842: Invalid SDK usage を回避できませんでした。 ### <i class="fa fa-wrench" aria-hidden="true"></i> 対処 SDKの中から `-[CLLocationManager requestAlwaysAuthorization]` の記述をすべて削除[^inrealprod]したところ、現象が発生しなくなりました。 [^inrealprod]: たやすく「すべて削除」などと書いていますが、実際はそこそこ面倒な調整を経てなんとか削除に至りました。 :::info App Clip に限ったことじゃないと思うのですが <br> > 「嘘じゃない!俺が見たときは確かに処理中だったんだ!」 みたいなことが普通に起きそうなので、デリバリが成功したファイルを無言で消す仕様はちょっと改善してほしかったですかね... (消した旨を App Store Connect にメッセージで表示するとか出来なかったのかな...) ::: <br><br><br> ## 最後に App Clip 開発を取り巻く環境は時間とともに改善されており、現在 Xcode12.2 がリリースされている時点においては、β版だった頃と比較して、特に苦労することもなく実装できるようになったのではないかと思います。 ただ、そうはいってもまだまだハマりどころがどこに隠れているかわからない節はあるので、App Clip開発は依然として「ある程度のiOS開発経験がある人向けのタスク」と考えるのが無難かもしれません。 <br><br><br> ## 参考 公式ドキュメント: - [Explore App Clips - WWDC 2020 - Videos](https://developer.apple.com/videos/play/wwdc2020/10174/) - [App Clips | Apple Developer Documentation](https://developer.apple.com/documentation/app_clips) その他、App Clip 開発にて役立つ記事を集めました。ぜひ読んでみてください。 - [君はAppClipを見たか](https://www.toyship.org/2020/10/11/001625) - [App Clipsに対応する](https://zenn.dev/d_date/articles/1a9539b7818729dfc228) - [App Clipの完全ガイド:App Clipの作成、Safariのバナーに追加したら、QRコードを生成し、情報を保存して位置情報と呼び出しURLを確認し、そして主要アプリを推奨します。](https://qiita.com/MaShunzhe/items/5b1c24a2bdb6952584ae)