iOS
AppClip
iOS14
requestAlwaysAuthorization()
の記述が 存在 してはいけません。筆者は
とあるiOSアプリ用SDKについて「AppClip上でも使用できるようにしたい」と相談されました。
App Clip について、実装方法や挙動について調べ、実際に試してみることにしました。
公式ドキュメント(App Clips)の他にも、WWDCのビデオ(Explore App Clips)が日本語字幕もあってわかりやすかったです。
App Clip の仕様把握はとても難航しました。
App Clip 自体の品質があまり高くない状態[1] だったので調査自体がかなり苦労を伴うものとなりました。
次のセクションで、印象に残ったトラブルをいくつか紹介します。
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"
文中の ABCDEFGH
は Team ID です。
「App Clip の App ID が、親の App ID を前方に含んでいないよ」というメッセージですが、ご覧のように含んでいる(プレフィックスになっている)のがわかります。どういうことでしょうか…
既存プロジェクトはCocoaPodsを利用していたのですが、AppClipターゲットを追加した際に なぜか Pods ディレクトリ以下にファイル一式を展開したらしく application identifier などを Pods.xcodeproj/project.pbxproj
から拾って来てしまったのが原因で、 App ID の不整合を起こしていたようでした。
たまたまプロジェクトディレクトリ全体をXcodeの外から串刺し検索してみようと思い至らなかったら原因は永久にわからなかったかもしれません…
Xcode上だとディレクトリ構造が実際の構成とは異なる構成で表示されることもあり、なかなか気づきませんでした。
Pods.xcodeproj/project.pbxproj
の PRODUCT_BUNDLE_IDENTIFIER
を直接修正[2]したらエラーは出なくなったのですが、そもそもPodsディレクトリ以下に展開されていることが問題なので、これは解決とは言えません。
結局、しばらくして Xcodeを最新にしたあとにターゲットを追加し直す ことで、現象が再現しなくなり、最終的な解決となりました。
プロジェクトの構造によっては起きないようで、現象が発生したケースにおいては、いまだ何が悪かったのか謎のままです…
実機向けにビルドする場合など、署名が必要な段階で Provisioning profile ***** doesn't support the On Demand Install Capable capability. というメッセージが表示され、エラーになりました。
プロジェクトに紐付いた Team ID がエンタープライズプログラムに加入しているのが原因でした。
App Clip はエンタープライズプログラムによる(In House ビルドによる)配布をサポートしていないとのことです。
https://developer.apple.com/forums/thread/654943?answerId=626595022#626595022
App Clips are unsupported in Enterprise apps.
そのため、On Demand Install Capable capability が自動的に付与されなかったと考えられます。
2020年9月当時、「エンタープライズプログラムだと利用できない」という情報はApple公式のドキュメント類には記載されていませんでした[3]。
新しく、エンタープライズプログラムに加入していない Apple アカウントを用意しました。
支払いが発生するので、現場によっては判子リレーが発生する大変面倒な作業ではないでしょうか…
App Clip にプッシュ通知を送るために、Apple Developer サイトからプッシュ通知証明書を生成したところ、異常な状態で出力されました。
具体的には friendlyName が 本来なら Apple Push Service となるところ(画像右側)、実際には Apple Distribution: xxx… のような文字列(画像左側)になっていました。
friendlyName が Apple Push Service 始まりの書式でない場合、多くのサードパーティプッシュ配信サービスにおいて証明書(PKCS#12ファイル)の登録に失敗する可能性があります。
App Clip 向けのプッシュ通知証明書を、親Appのプッシュ通知証明書よりも先に作成したのが原因のようでした。
私には不具合にしか見えなかったのですが、もしかしたらこういう仕様にならざるをえない理由があるのかもしれません。
親Appのプッシュ通知証明書を作成したあとにApp Clip 向けのプッシュ通知証明書を作成したところ、現象は発生しなくなりました。
「今どきプッシュ通知はみんなp8鍵使ってるから」みたいな理由で確認が後回しにされた感がなくはないです…
位置情報を利用するSDKを App Clip に組み込み、親App と一緒に App Store に提出したところ、デリバリが成功したあとに、処理中の状態だった App が消失する現象が起きました。
不審に思いメールボックスを確認すると、App Store から「ITMS-90842: Invalid SDK usage」が発生した旨のメールが届いていました。
つまり、App Store 上で ITMS-90842 を理由に App が消去された、ということでした。
SDK内部に -[CLLocationManager requestAlwaysAuthorization]
の記述が存在していたこと原因でした。
一応、SDKの中では「App Clip 上で起動した場合は -[CLLocationManager requestAlwaysAuthorization]
をコールしない」ように実装していたのですが、どうやらコールしないようにするだけでは駄目だったようで[4]、 -[CLLocationManager requestAlwaysAuthorization]
の記述そのものが存在してはならない ようでした。
SDKの中から -[CLLocationManager requestAlwaysAuthorization]
の記述をすべて削除[5]したところ、現象が発生しなくなりました。
App Clip に限ったことじゃないと思うのですが
「嘘じゃない!俺が見たときは確かに処理中だったんだ!」
みたいなことが普通に起きそうなので、デリバリが成功したファイルを無言で消す仕様はちょっと改善してほしかったですかね…
(消した旨を App Store Connect にメッセージで表示するとか出来なかったのかな…)
App Clip 開発を取り巻く環境は時間とともに改善されており、現在 Xcode12.2 がリリースされている時点においては、β版だった頃と比較して、特に苦労することもなく実装できるようになったのではないかと思います。
ただ、そうはいってもまだまだハマりどころがどこに隠れているかわからない節はあるので、App Clip開発は依然として「ある程度のiOS開発経験がある人向けのタスク」と考えるのが無難かもしれません。
公式ドキュメント:
その他、App Clip 開発にて役立つ記事を集めました。ぜひ読んでみてください。
iOS 14.0.1 のころですら、AppClipの起動時に2〜3回に1回の割合でクラッシュする現象が確認できていたほどです。 ↩︎
記述した覚えのない文字列が埋まっていたので {team_id}.{App Clip の Bundle ID}
の書式になるように修正しました。 ↩︎
探し方が悪いだけで実はあったのかもしれませんが…私は未だにフォーラム以外では見つけられてないです。 ↩︎
-[CLLocationManager requestAlwaysAuthorization]
を到達不能コードにした状態でSDKをビルドし、アプリに実装して確認しましたが、 ITMS-90842: Invalid SDK usage を回避できませんでした。 ↩︎
たやすく「すべて削除」などと書いていますが、実際はそこそこ面倒な調整を経てなんとか削除に至りました。 ↩︎