ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
StoreKit 2とXcodeでのStoreKitテストの新機能
XcodeでのStoreKit 2とStoreKitテストの最新の改善点を紹介します。プロモーション対象のアプリ内課金、StoreKitメッセージ、トランザクションモデル、RenewalInfoモデルおよびサブスクリプション管理のためのApp Storeシートに関するAPIアップデートをご覧ください。デバイス上のレシート検証のためにSHA-256にアップグレードし、APIを使用してSwiftUIビューを作成する方法を学びましょう。また、アプリ内課金とサブスクリプションのデバッグとテストができるよう、XcodeでのStoreKitテストを始めるお手伝いをします。Transaction Inspectorを紹介し、StoreKit構成エディタの最新のアップデートと、アプリのエラー処理をテストするためにStoreKitエラーをシミュレートする方法も確認します。
リソース
- Message
- Setting up StoreKit Testing in Xcode
- StoreKit
- Submit feedback
- Supporting promoted In-App Purchases in your app
- Testing failing subscription renewals and In-App Purchases
- Turn on Family Sharing for in-app purchases in App Store Connect
関連ビデオ
WWDC23
WWDC22
WWDC21
-
ダウンロード
♪ ♪
こんにちは Rickyです 「StoreKit 2の新機能と XcodeでのStoreKitテスト」にようこそ このセッションでは 今年 StoreKitにもたらした新機能と Xcodeでのテスト体験の 改善についてお話しします StoreKit 2は2021年の WWDCで初めて紹介され Swiftを使った新しく より柔軟なAPIが搭載されました 今年はStoreKit 2を さらに改善する新機能を ご紹介するのが楽しみです まずStoreKitフレームワークの 新機能をレビューし 次にStoreKitを使ってSwiftUIアプリを ビルドするためのアップデートを紹介し 最後にXcodeのStoreKitテストの 新機能を取り上げます iOS16.4から利用できる アプリ内課金を管理するための 新しいSwift APIを紹介できることを 嬉しく思います プロモーション対象のアプリ内課金は App Storeのプロダクトページで プロダクトを販売できる機能で それぞれに専用の プロモーション画像があります アプリ内課金のプロモーションは プロダクトの認知度を高める 最適な方法で App Store Connectで簡単に プロモーションを設定できます プロモーション対象のアプリ内課金の 構成については 「What's new in App Store Connect」 をご覧ください プロモーション対象のアプリ内課金は App Storeに表示されるため カスタマーがプロモーション対象の プロダクトを購入する場合 購入ボタンをタップすることで インタラクションが開始します その後 App Storeから 購入データがアプリに送信され この情報を受け取り 購入完了を促すことができます プロモーション対象の購入を受け取るには カスタマーがApp Storeでプロモーション 対象プロダクトの購入を開始するたびに 新しい購入インテントを受信する Swiftの非同期シーケンスを使用します まず PurchaseIntent.intentsを使用して 購入インテントを受信する リスナーを作成します シーケンスが新しいオブジェクトを 受信するたびに そのオブジェクトには購入に関連付けられた StoreKit Productが含まれます 通常通りにカスタマーに プロダクトの購入を促すには purchase()を呼び出し おなじみの支払い画面を表示させ そこでインタラクションを 完了するようにします アプリに購入完了の準備が できていない場合は ローカルにインテントを保存して 延期することもできます あとでいつでも処理できます
アプリ内課金をプロモーションする もう1つの特徴は 現在のデバイス上で ローカルにプロダクトを表示する方法を カスタマイズできることです 例えば カスタマーがいずれかのプロダクトを 購入した場合 そのプロダクトを非表示にして ブラウズまたは検索時にApp Storeが そのプロダクトを再び表示しないようにできます また アプリの現在の状態 例えばゲームの ゲームのレベルアップなどに基づき プロダクトの順番の変更や 紹介するプロダクトのサブセットの変更もできます これらのすべてのケースをカバーするため プロモーション対象のアプリ内課金の 順序と可視性のカスタマイズに使用できる― 新しいSwift APIを 複数ご紹介するのが楽しみです 簡単なデモを見てみましょう StoreKitのインポート後 Product.PromotionInfo.currentOrderで 現在のプロモーションの順序が確認できます これは現在設定されている順序で PromotionInfoオブジェクトの シーケンスを返します このリストが空の場合 このデバイスにローカルオーバーライドが 設定されていないことを意味し App Storeで表示されるプロダクトはApp Store Connectで構成した順序と同じです このシーケンス内の各オブジェクトには アプリのプロモーション対象のプロダクト に関する情報が含まれています プロモーションの カスタム順序を設定するには Product.PromotionInfo. updateProductOrder APIを使用して このデバイスのApp Storeに 表示させたい順序で プロダクトIDのリストを渡します また 全く新しい順序を設定することなく プロダクトの非表示や表示設定もできます プロモーション対象の アプリ内課金に関連付けられた― visibilityプロパティを 変更すれば可能です 表示状態は表示や非表示または App Store Connectで構成した― 設定に従うデフォルトの いずれかにすることができ アプリによってローカルオーバーライドが 設定されていない全デバイスに適用されます コードでの変更方法を見てみましょう
可視性の値は 異なる複数の方法で変更できます アプリは Product.PromotionInfo. updateProductVisibility APIを 呼び出しや新しい可視性の状態と アプリ内課金のIDを 両方渡すことで 単一のプロダクトの値を変更できます また 各PromotionInfoオブジェクトの メンバープロパティの設定による 可視性の値の変更も可能です 変更を保存するには 先ほど変更した オブジェクトにupdate() を呼びます 以上で StoreKit 2で アプリ内課金のプロモーションを 始めるために必要なことはすべて完了です それでは StoreKit 2でコアとなる データモデルの強化点を複数紹介します
これらのモデルは アプリ内課金や関連情報 例えば購入日や 定期購入のステータスなどを 管理する際に便利です Transactionと RenewalInfo- データモデルに追加された 新しいフィールドについて説明します
最初の新しいフィールドはstorefrontで storefrontCountryCodeとともに Transactionモデルに表示されます 次の新しいフィールドはreasonです これは カスタマーが購入を開始したのか トランザクションがサブスクリプションの 自動更新なのかを示します Product.SubscriptionInfoの RenewalInfoモデルには nextRenewalDateという 新しいメンバーがあります これはサブスクリプションの更新が いつ処理されるかを示します これらの新しいフィールドはすべて Xcode 15でビルドしたアプリで利用可能で 当初はiOS 17でリリースされましたが StoreKit 2を使用している場合 そのほとんどは 以前のiOSバージョンでも 遡及して動作します 次に StoreKitメッセージと 追加したての新機能についてお話しします App Storeがカスタマーに重要な情報を 通知する方法として 昨年のWWDC 2022で Message APIを紹介しました メッセージにはメッセージの 目的を伝えるReason値があります アプリはメッセージを延期するか 抑制するかを選択できます 例えば インタラクションフロー中に メッセージを表示すると カスタマーの邪魔になる場合は メッセージの非表示を選択できます そうでない場合 StoreKitは アプリの起動時にアクティブなメッセージを 自動的に表示します 今年 billingIssueという 新しいメッセージの理由を追加しました このメッセージは iOS 16.4から利用できます App Storeは請求の問題で サブスクリプションの更新に 失敗したときに このメッセージを送信します StoreKitは 請求の問題に関するシートを表示し カスタマーはアプリを離れることなく 問題を解決できます この新しいプロパティはSandboxで すでに有効になっています すべてのカスタマーに対して これが有効になる時期については Apple Developer Webサイトで 今年の後半にお知らせします App Storeが サブスクリプションの更新に失敗すると サブスクリプションは 支払いの再試行状態になります Sandboxで本機能を テストする方法については アプリ内課金のテストに関する WWDCのセッションを参照してください セキュリティ関連のアップデートを いくつか確認しましょう StoreKitを最新の セキュリティプラクティスに 対応させるため オリジナルのStoreKitのレシートの 署名証明書を SHA-1からSHA-256に移行しました OpenSSLなどの 最新バージョンの暗号ライブラリは すでにSHA-256をサポートしていますが デバイス上でレシートの検証を行う― アプリの場合は 新しい証明書の 適切な処理を確認することが重要です 新しいSHA-256署名証明書は 6月20日からSandboxでの レシート署名に使用され iOS 16.6および macOS 13.5以降を実行している デバイスでテスト可能になります 8月14日以降 新証明書は App Storeに提出された― すべての新しいアプリおよび アプリのアップデートの レシートへの署名に使用されます スケジュールの詳細は Apple Developer Webサイトをご覧ください アプリがStoreKit 2を使用している 場合は 何もする必要はありません StoreKit 2の Signed Transaction Renewal Info App Transactionは 現在すでにSHA-256を使用しています App StoreのサーバーAPIを使って レシートの検証を行っている場合も 新しいフォーマットに自動対応しているため 何も変更する必要はありません 次に SwiftUIを使用してアプリで アプリ内課金を非常に 簡単かつ迅速に商品化する StoreKitの全く新しい機能セットを お見せできるのが楽しみです 単一のアプリ内課金 全プロダクトのストア さらにはサブスクリプションに特化した カスタム向けのSwiftUIビューを 作成するための新しいAPIがあります これらは通常の SwiftUIのビューのように機能し 実装には最小限のコードしか 必要としません 新しいビューを見てみましょう このプロダクトビューを使うことで ローカライズされたタイトルや 説明 そしてオプションの プロモーション画像まで含めて 単一のアプリ内課金を表すことができます ProductViewにプロダクトIDを 渡すことで作成できます また StoreKitのプロダクトを 読み込む必要もありません productIDの文字列を使うだけです StoreKitとSwiftUIが 残りを処理します アプリ内の店舗のように プロダクトのコレクション― 全体を表示する新しいビューもあります 単一のプロダクトIDを渡す代わりに StoreViewと組み合わせ productIDのコレクションを使用することで 販売するプロダクトのリストを作成し SwiftUIコンポーネントを使用して さらにカスタマイズすることができます StoreViewは アプリやゲームを開始し アプリ内課金をサポートする 素晴らしい方法です セットアップには以下に示すように 数行のコードしか必要ありません 最後になりましたが 利用可能なすべての サービスレベルでサブスクリプションを 商品化するための新しいビューもあります SubscriptionStoreViewを使用すると サブスクリプショングループの カスタムページをすばやく作成できます 必要なのはsubscriptionGroupIDだけで これは通常App Store Connectで 見つけることができますが StoreKitの構成でも Xcode上で利用できるようになりました 新しいビュータイプには 簡単に追加できるカスタマイズが たくさんあります 例えば カスタム背景を作成するために 数行のコードを変更するだけで このSubscriptionStoreViewの外観が 大きく変わることを確認してください これらのサブスクリプションの 新しい変更に伴い StoreKitアプリ内での サブスクリプションの選択と操作の 新しい体験を提供できるよう サブスクリプション管理シートを追加しました 見てみましょう
ここではサブスクリプションを管理する おなじみのフローが表示されます これによりカスタマーに 現在のアクティブなレベルが表示され 各レベルをタップして そのサブスクリプショングループで 利用可能なほかのレベルのリストを 表示するオプションが提供されます このプロセスをより迅速にし より多くのカスタマイズを 提供するために ステップを飛ばし 表示したいサブスクリプショングループに すぐにジャンプできる別のビューがあります 例えば 複数の サブスクリプショングループがある場合 アプリのコンテキストで関連する サブスクリプショングループを選択し カスタマーが選択できるほかの サービスレベルを表示することができます このシートは 通常と同じAPIである― .manageSubscriptionsSheetで 使用できます 今回はさらにsubscriptionGroupID パラメータを渡します StoreKitでSwiftUIアプリを 作成するトピックでは ほかにもたくさんのビューや アプリのデザインに合うよう 適用できるカスタマイズなど 紹介したいことがまだ多数あります 詳しく知りたい場合は 「Meet StoreKit for SwiftUI」で Gregが解説してくれます StoreKitのアプリ内課金の 新機能を確認したあと XcodeのStoreKitテストで 新ツールでのテスト方法を確認しましょう まずはXcode 15からです XcodeのStoreKitテストを 使用すると App Store Connectで 何かを設定する前であっても StoreKitを使用したアプリが ビルドを開始した時点から優れた 体験を提供することが確認できます よって Macでテストしながら StoreKitに関連するアクションの テストや管理 編集ほか 作成もすることができ シミュレータとデバイスの 両方でサポートされています トランザクションマネージャを始め アプリのデバッグと テストのための新機能があります すべてのテストアプリを 整理できるようになりました ナビゲータではテスト用の StoreKitコンフィギュレーションを使用して 現在のStoreKitアプリが インストールされている― 接続中のすべてのデバイスと シミュレータを確認できます これにより複数デバイスでの 同時テストがより簡単かつ迅速になり 購入履歴の確認のために アプリを実行する必要はありません さっそく試してみましょう iPhoneをMacに接続し シミュレータを起動しています さらに 開発中の新しいゲームである Backyard Birdsを使用中です Xcodeを開くと プロジェクトを 開いているかどうかに関係なく Debug StoreKit Manage Transactionsへと進み すでにお馴染みの トランザクションマネージャの ビューが表示されます ナビゲータには 現在Macに接続中の すべてのデバイスが表示されます 私の場合は 物理的なiPhoneとシミュレータです このリストには Backyard Birdsを含む 複数のアプリが表示されています これらはすべてXcodeで StoreKitテストを使用するアプリで デバッグセッション外で 検査することができます これらのデバイスでアプリをクリックすると そのアプリのStoreKit トランザクションのリストが表示され 昨年紹介した詳細サイドバーを使って それぞれ検査することができます これはBackyard Birdsの Xcodeプロジェクトを開いて シミュレータ上で 実行した場合も機能します
この場合 アプリ名の横に 小さなインジケータが表示されるので どのアプリがアクティブに デバッグされているかもわかります トランザクションマネージャの新機能は これだけではありません Xcodeを使ってMacから直接アプリ内での 購入ができるようになりました さらに 新しい購入を作成する際に 消耗型プロダクトの数量や 定期購入のオファーコードなど 様々な購入パラメータを カスタマイズすることもできます また サブスクリプション対して オファーコードを選択することもできます
Backyard Birdsで どのように機能するか見てみましょう まず テストしたいアプリを 選択する必要があります 次に フィルターバーの左側の プラスボタンをクリックし 新規購入を作成します 表示されたポップアップには アプリで利用可能なアプリ内課金がすべて リストアップされています これらはStoreKitの構成で 構成したものと同じプロダクトです 消耗型プロダクトを購入するので Nutrition Pelletを 選択して Nextをクリックします
ここで 新しい購入を 構成する機会がありますが スキップしたい場合は デフォルトのオプションも有効です 設定に満足しているので Doneをクリックし これらのパラメータを使って 購入を完了させます
シミュレータでは アプリは動作していませんが StoreKitは新しい購入を 受信して処理しました 取引リストを見ると 一番上に新しいアイテムがあります クリックすると新しいトランザクションの 詳細を見ることができます サブスクリプションは異なるので 別の購入をしてみましょう もう一度プラスボタンをクリックして 新規購入を作成し 今回はこのアプリで サブスクリプションの名前を検索し 探しているものを選んで Nextをクリックします
アプリ内課金の種類が変わったため 購入を構成するオプションが変わりました 購入日のように同じものもありますが 新しいものもいくつかあります 何をするか説明しましょう ちなみに デフォルトのプロパティは ここでも有効です
StoreKitの構成で オファーコードが設定されている場合 サブスクリプションのオファーコードを 選択するオプションがあります カスタマーはオファーコードや プロモーションを入力する必要がありますが テストを容易にするため このproductIDで利用可能な オファーのリストを提供します この場合 購入日を変更し まるで昨年のWWDC中に このサービスに初めて申し込んだかのように 正確に1年前に設定したいと思っています 次に このサブスクリプションを 自動更新にするか 1つのサブスクリプション期間 このプロダクトの場合は1カ月だけ サブスクリプションを 維持するかを選択できます 私は自動更新を有効にしておきたいので アプリがアクティブな サブスクリプションをどう扱うか 使い始める前にテストすることができます 完了をクリックして購入を完了し 取引リストをフィルタリングして 結果を見てみましょう
予想通り 昨年から毎月1回更新しています アプリが起動しておらず 受信機会がなかったため これらはすべて 現在未完成と表示されています シミュレータで実行して Backyard Birds Passに アクセス可能になったことを確認しましょう
トランザクションマネージャの新機能は iOS 17と macOS 14から始まる XcodeのStoreKitテストを すでにサポートしているすべての デバイスとプラットフォームで動作します また iPadOS watchOS tvOSを含む ほかのプラットフォー ムでもサポートされています 古いバージョンのオペレーティング システムを実行している場合 何も変化はありません トランザクションマネージャはアクティブな デバッグセッションを使用する場合 以前と同じすべての機能と互換性があります 次に StoreKitアプリが様々なシナリオで どのように動作するかを より詳細にテストできる― StoreKit構成の新機能を紹介します これを実証するために Backyard Birdsの Xcodeプロジェクトを開き StoreKit構成に移動します
構成済みのアプリ内課金の上に Configuration Settingsという 新しい項目があります アプリのテスト環境に 構成可能なオプションを 提供するために追加した新しいメニューで すでにお馴染みのものもあれば Xcode 15から新たに 追加されたものもあります 最初のセクションと2番目のセクションは デフォルトのストアフロントや 価格設定と利用可能性に 使用するロケールなど 既存のすべてのオプションをカバーします また サブスクリプションの更新速度や 購入承認の強制などの機能も含まれています Xcodeの以前のバージョンでは StoreKitの構成を開くと Editorメニューに引き続き これらの項目があり 互換性のある方法で使用できます StoreKitのテストオプションについて 話している間に 今年iOS 16.4で追加した新しい サブスクリプション更新レートがあります サブスクリプションの有効期限の更新ごとに 変更するように設計されており サブスクリプションの 実際の期間よりも 早く一貫した 更新を生成する際に役立ちます サブスクリプションの長期的な状態の 迅速かつ信頼性の高い テストに非常に便利です これらの新しい構成可能なレートは Xcode 15のEditorメニューと StoreKit構成設定の 両方で見つけられます StoreKitの構成設定の 3番目のセクションは アプリでStoreKitのエラーを シミュレートするために 使用できるオプションをカバーしています エディタメニューにあった Fail Transactions サブメニューが拡張され さらに多くのStoreKit API と エラータイプをサポートします 各オプションはアプリが使用する 可能性のあるStoreKit 2 APIを表し そのAPIがアプリから呼び出されたときに 毎回投げるべきエラーを選ぶことができます この機能では 数多くの APIがサポートされています プロダクトのローディングの問題 購入の失敗 レシートや トランザクションの検証の問題や 払い戻し要求など 様々なテストが可能です 実際にどのようなものか見てみましょう
左側にBackyard Birdsの Xcodeプロジェクトを開き 右側にシミュレータで アプリを実行しています StoreKitの構成では Purchase API名の隣にある― チェックボックスを使って 購入エラーを有効にし 投げられるエラーを選択することができます
カスタマーがストアフロントを変更したときに アプリがどのように 購入を処理するかテストしたいので Product Unavailableを選びます
このファイルは編集時に自動的に保存され アプリの実行時にも デバイスに同期されるため アプリを再実行することなく 変更をすぐにテストできます プロダクトを購入し 何が起こるか見てみましょう
予想通り 失敗しました このプロダクトは購入できませんので デベロッパにお問い合わせくださいと 表示されます
購入エラーを無効にして もう一度試してみましょう
以上の手順で このアプリコードが 購入時にこのようなエラーが発生しても 対処できることを効果的にテストできました この方法は StoreKitの 構成設定にある― どのAPIやエラーオプションにも適用でき 複数のシナリオをカバーし アプリが堅牢であることを保証します これらのエラーはすべて StoreKitの一部であり すでに遭遇したことがあるかもしれません それぞれのエラーはアプリ内での 明確な失敗の事例を示しています XcodeのStoreKitテストの 新機能は以上です 今日は デバッグセッション外で 複数デバイスのトランザクションを 検査して管理する方法や アプリが既存の購入を どのように処理するかをテストするために トランザクションマネージャから プロダクトを購入する方法 そして可能性ある多くの失敗シナリオを カバーするためにStoreKitエラーを シミュレートする方法を紹介しました
Xcodeのこれらの新機能はすべて StoreKit Testフレームワークを使って アプリのユニットテストを書くことで 同じタスクを実行するオートメーションを 書くことができます XCTestセッションで デバイス外での購入を作成し シミュレートされたエラーを設定する 新しいAPIを見てみましょう 新しいアプリ内課金を作成するために StoreKitTestには StoreKit purchase(_:) APIと 同じように動作する― 新しいSwift APIがあり 購入オプションも同じです 購入日を変更するような 新しい購入機能をサポートするために テスト用に新しい 購入オプションも追加しました 例を見てみましょう SKTestSessionをセットアップした後 定期購入のデバイス外購入を行い 購入日を今日から1年前に上書きしています これは私がトランザクションマネージャで 行ったのと同じ購入で 全く同じように動作し 再現可能な結果を作成し アプリのテストを自動化することができます また StoreKitTestには SKTestSessionで StoreKitのエラーを シミュレートするための新しいAPIが 複数用意されており StoreKitの構成設定で シミュレートされるエラーと 同様に動作します テストセッションを作成したら テストしたいエラーの種類と シミュレートするStoreKit APIを 指定して setSimulatedErrorを呼び出します この例では loadProducts APIの ネットワークエラーをシミュレートします このテストで loadProducts APIを呼び出すと 常に同じエラーが発生します シミュレーションによる失敗を 無効にするには 同じセッターAPIを使用し エラータイプの代わりにnilを渡します 最後に 新しいサブスクリプション 更新レートのAPIもあります これらは既存のものと同様に SKTestSessionの timeRateという メンバーを介してアクセスできます この定期購入のテスト例では より高速な更新レートを設定し 複数の更新を素早く生成するために コードを1行追加しました 今日は Xcodeの機能における 新しいStoreKitとStoreKitテストが 多数取り上げられました StoreKitにはアプリ内課金を プロモーションするための新しいAPIがあります また Transactionと RenewalInfoのデータモデルが強化され より価値のある情報が 手に入るようになりました さらに請求に関する問題を処理するために リッスンできる― 新しいメッセージタイプも追加されました SwiftUIの新しいStoreKitビューは マーチャンダイジングをサポートする アプリを素早く構築する優れたツールで あらゆるデバイスで動作させるために 余分なコードは必要ありません 最後に XcodeのStoreKitテストで 提供される― 優れたツールを使って アプリ内の すべてのStoreKit機能を検証できます StoreKit 2には 素晴らしいアプリを構築し ビジネスを成長させる素晴らしい機能が たくさん詰まっています Swiftを最大限に活用する 多くのツールが追加され シンプルでありながら強力な新しいAPIにより カスタマーエクスペリエンスの構築に もっと集中することができます プロダクトや定期購入を扱うアプリはすべて StoreKit 2で 構築できるようになりました まだStoreKit 2を未使用の方は ぜひ試してみてください すでに利用されている場合は 今日紹介した 新機能の感想をお聞かせください 既存のアプリで新しいアプリ内課金の マーチャンダイジングビューを使って 体験をカスタマイズしたり これらの新しいAPIのみを使用して 新しいものを作成したりできます また XcodeのStoreKitテストを使えば コードをテストし あらゆる条件下で カスタマーに最高の体験を 提供するためにすべてが期待通りに 動作することを確認できます その他StoreKitの機能については 以下のリンク先のセッションをご覧ください StoreKit 2を使って みなさんが何を開発されるのか楽しみです ご視聴ありがとうございました
-
-
1:42 - Create a listener for promoted in-app purchases
// Create a listener for promoted in-app purchases import StoreKit let promotedPurchasesListener = Task { for await promotion in PurchaseIntent.intents { // Process promotion let product = promotion.product // Purchase promoted product do { let result = try await product.purchase() // Process result } catch { // Handle error } } }
-
2:57 - Check promotion order
// Check promotion order import StoreKit do { let promotions = try await Product.PromotionInfo.currentOrder if promotions.isEmpty { // No local promotion order set } for promotion in promotions { let productID = promotion.productID let productVisibility = promotion.visibility // Check promoted products } } catch { // Handle error }
-
3:26 - Set a promotion order
// Set a promotion order import StoreKit let newPromotionOrder: [String] = [ "acorns.individual", "nectar.cup", "sunflowerseeds.pile" ] do { try await Product.PromotionInfo.updateProductOrder(byID: newPromotionOrder) } catch { // Handle error }
-
4:02 - Update promotion visibility
// Update promotion visibility import StoreKit // Hide “acorns.individual” do { try await Product.PromotionInfo.updateProductVisibility(.hidden, for: "acorns.individual") } catch { // Handle error }
-
4:17 - Update promotion visibility (alternative method)
// Update promotion visibility import StoreKit do { let promotions = try await Product.PromotionInfo.currentOrder // Hide the first product if var firstPromotion = promotions.first { firstPromotion.visibility = .hidden try await firstPromotion.update() } } catch { // Handle error }
-
8:32 - Product view
// Product view import SwiftUI import StoreKit struct BirdFoodShop: View { let productID: String let productImage: String var body: some View { ProductView(id: productID) { BirdFoodProductIcon(for: productID) } .productViewStyle(.large) } }
-
8:52 - Store view
// Store view import SwiftUI import StoreKit struct BirdFoodShop: View { let productIDs: [String] var body: some View { StoreView(ids: productIDs) { product in BirdFoodIcon(productID: product.id) } } }
-
9:19 - Subscription view
// Subscription view import SwiftUI import StoreKit struct BackyardBirdsPassShop: View { let groupID: String var body: some View { SubscriptionStoreView(groupID: groupID) } }
-
21:09 - Simulated off-device purchase using StoreKitTest
// Simulated off-device purchase using StoreKitTest import StoreKit import StoreKitTest func testSubscriptionRenewal() async throws { let session = try SKTestSession(configurationFileNamed: "Store") let oneYearInterval: TimeInterval = (365 * 24 * 60 * 60) let transaction = try await session.buyProduct( identifier: "birdpass.individual", options: [ .purchaseDate(Date.now - oneYearInterval) ] ) // Inspect transaction }
-
21:48 - Set a simulated purchase error when loading products
// Set a simulated purchase error when loading products import StoreKit import StoreKitTest func testLoadProducts() async throws { let session = try SKTestSession(configurationFileNamed: "Store") let productIDs = [ "acorns.individual", "nectar.cup" ] // Set a simulated error, then load products, expecting an error session.setSimulatedError(.generic(.networkError), forAPI: .loadProducts) do { _ = try await Product.products(for: productIDs) XCTFail("Expected a network error") } catch StoreKitError.networkError(_) { // Expected error thrown, continue... } // Disable simulated error session.setSimulatedError(nil, forAPI: .loadProducts) }
-
22:24 - Set a faster subscription renewal rate in a test session
// Set a faster subscription renewal rate in a test session import StoreKit import StoreKitTest func testSubscriptionRenewal() async throws { let session = try SKTestSession(configurationFileNamed: "Store") // Set renewals to expire every minute session.timeRate = .oneRenewalEveryMinute let transaction = try await session.buyProduct(identifier: "birdpass.individual") // Wait for renewals and inspect transactions }
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。