Adapty iOS SDK を v4.0 に移行する

Adapty iOS SDK 4.0 ではフローが導入され、ペイウォール API の名称が変更されました。新しい API はフローと連携しており、旧ビルダーのペイウォールにも引き続き対応しています。Adapty ダッシュボード側での設定変更は不要です。

クイックリファレンス

v3v4
Adapty.getPaywall(placementId:locale:)Adapty.getFlow(placementId:)
AdaptyUI.getPaywallConfiguration(forPaywall:)AdaptyUI.getFlowConfiguration(forFlow:locale:)
Adapty.getPaywallProducts(paywall:)Adapty.getPaywallProducts(flow:)
Adapty.logShowPaywall(_:)Adapty.logShowFlow(_:)
AdaptyPaywallControllerAdaptyFlowController
AdaptyPaywallControllerDelegateAdaptyFlowControllerDelegate
AdaptyUI.paywallController(with:delegate:)AdaptyUI.flowController(with:delegate:)
.paywall() (SwiftUI modifier).flow()
AdaptyPaywallViewAdaptyFlowView
didFailRenderingWith: / didFailRendering:didReceiveError:
didFinishPurchase(オプション、成功時に自動で閉じる)didFinishPurchase(必須、自動では閉じない)
Adapty_KidsMode / AdaptyUI_KidsMode パッケージプロダクトKidsMode パッケージトレイト
Adapty.updateAttribution(_:source:) (source: String)Adapty.updateAttribution(_:source:) (source: AdaptyAttributionSource)
Adapty.setIntegrationIdentifier(key:value:)Adapty.setIntegrationIdentifier(_:) (AdaptyIntegrationIdentifier)

iOS 最小バージョン

Adapty iOS SDK 4.0 では、最小デプロイメントターゲットが iOS 13.0 から iOS 15.0 に引き上げられました。アップグレードの前に、プロジェクトの iOS Deployment Target を 15.0 以上に設定してください。

インストール:CocoaPods のサポート終了

Adapty iOS SDK 4.0 では CocoaPods のサポートが廃止されました。SDK のインストールには Swift Package Manager をご利用ください。また、v4 のパッケージマニフェストが Swift tools 6.2 を宣言しているため、Xcode 26 以降が必要です。

プロジェクトでまだ CocoaPods を使用している場合は、Podfile から Adapty および AdaptyUI pod を削除し、pod install を実行してクリーンアップした後、Xcode で File → Add Package Dependency から https://github.com/adaptyteam/AdaptySDK-iOS.git を使ってパッケージを追加してください。

キッズモード: 専用プロダクトからパッケージトレイトへ

v3 では、キッズモードを有効にするには、専用の Adapty_KidsMode および AdaptyUI_KidsMode パッケージプロダクトを選択し、import 文をリネームする必要がありました。v4.0 ではこれらのプロダクトが削除されました。キッズモードは、通常の Adapty パッケージ上の KidsMode という Swift パッケージトレイトとなり、有効にすると SDK 全体で IDFA および AdSupport がコンパイル時に除外されます。

移行手順:

  1. Choose Package Products ウィンドウで、Adapty_KidsMode および AdaptyUI_KidsMode の代わりに、通常の Adapty および AdaptyUI プロダクトを選択します。

  2. KidsMode トレイトを有効にします。Xcode 26.4 以降をお使いの場合は、プロジェクトの Package Dependencies ビューで AdaptySDK-iOS 依存関係に対して有効にしてください。Package.swift で Adapty を依存関係として追加する場合(swift-tools-version 6.1 以降が必要)は、そちらで有効にします:

    .package(
        url: "https://github.com/adaptyteam/AdaptySDK-iOS.git",
        from: "4.0.2",
        traits: ["KidsMode"]
    )
  3. インポートを通常のモジュールに戻します:

   - import Adapty_KidsMode
   - import AdaptyUI_KidsMode
   + import Adapty
   + import AdaptyUI
Note

Xcode 26.4 より前のバージョンでは、UI からプロジェクトにトレイトを有効化できません。その場合は、KidsMode トレイトを有効にした Adapty に依存するローカルの Swift パッケージを作成し、アプリターゲットがそのパッケージに依存するように設定してください。

削除された API

  • Adapty.getPaywallProductsWithoutDeterminingOffer(paywall:) — 削除されました。すべてのプロダクトにオファー情報が含まれるようになったため、個別の対象資格確認パスは不要になりました。
  • AdaptyPaywallProductWithoutDeterminingOffer — 削除されました。以前このタイプを渡していたコールバック(didSelectProduct など)は、今後 AdaptyPaywallProduct を渡すようになります。

App Store プロモート購入処理の一時的な削除

StoreKit 2 への移行の一環として、Adapty iOS SDK 4.0 では App Store プロモートのアプリ内課金を処理する API が削除されました。shouldAddStorePayment(for:) デリゲートメソッドと、それが受け取る AdaptyDeferredProduct 型は 4.0 では利用できません。このような購入は引き続き完了し、Adapty がトランザクションを記録しますが、4.0 ではアプリがそれをインターセプトまたは遅延させる手段がありません。

Warning

この削除は4.0にのみ適用されます。この処理はSDK 4.1で新しいAPIとともに復活します。アプリがApp Storeのプロモーション済みアプリ内課金をインターセプトしている場合は、3.xから直接4.1に移行してください。App StoreからのIn-app purchasesを参照してください。

ペイウォールの取得

getPaywall + getPaywallConfiguration → getFlow + getFlowConfiguration

返される型が AdaptyPaywall / AdaptyUI.PaywallConfiguration から AdaptyFlow / AdaptyUI.FlowConfiguration に変わります。locale パラメータはフェッチ呼び出しから getFlowConfiguration に移動します。AdaptyFlow は paywalls も公開しており、これはフローのペイウォールバリエーションを AdaptyFlowPaywall の値として返します。Web ペイウォールのメソッドはこれらのいずれかを受け取ります。

- let paywall = try await Adapty.getPaywall(placementId: "YOUR_PLACEMENT_ID", locale: "en")
- let paywallConfiguration = try await AdaptyUI.getPaywallConfiguration(forPaywall: paywall)
+ let flow = try await Adapty.getFlow(placementId: "YOUR_PLACEMENT_ID")
+ let flowConfiguration = try await AdaptyUI.getFlowConfiguration(forFlow: flow, locale: "en")

getPaywallProducts(paywall:) → getPaywallProducts(flow:)

getPaywallProducts は、Adapty.getFlow によって返された AdaptyFlow を受け取るようになりました:

- let products = try await Adapty.getPaywallProducts(paywall: paywall)
+ let products = try await Adapty.getPaywallProducts(flow: flow)

フォールバックファイル

フォールバックファイルの形式は SDK v4 で変更されました。Placements > Fallbacks から新しいファイルをダウンロードし、アプリにバンドルしてください。

ペイウォールの表示を記録する

logShowPaywall(:) → logShowFlow(:)

logShowPaywall は logShowFlow に名称変更され、AdaptyPaywall の代わりに AdaptyFlow を受け取るようになりました。イベントは引き続き同じバリエーションに対して記録されるため、既存のファネルや A/B テストの指標はダッシュボードを変更せずにそのまま機能します。

- try await Adapty.logShowPaywall(paywall)
+ try await Adapty.logShowFlow(flow)

v3 と同様に、Adapty がレンダリングするフローやペイウォールを表示する際はこのメソッドを呼び出す必要はありません。Adapty がそれらのビューを自動的にトラッキングします。

didFinishPurchaseが必須になりました

v3では、didFinishPurchaseはオプションでした。実装しなかった場合、購入成功後にペイウォールが自動的に閉じられていました。v4.0では、この自動クローズのデフォルト実装が削除されました。これにより、購入成功後もフローを継続できます。たとえば、フローの残りのスクリーンを表示し続けることが可能です。購入後の動作はご自身で決定してください。スクリーンを閉じるか、何もせずにフローを継続させるかを選べます。

  • UIKit: AdaptyFlowControllerDelegate の準拠者は didFinishPurchase を実装する必要があります。デフォルト実装は廃止されました。
  • SwiftUI: .flow(...) および AdaptyFlowView(...) の didFinishPurchase クロージャが必須になりました。didFailPurchase および didFinishRestore と同様です。

v3 の動作を維持するには、自分で画面を閉じてください:

func flowController(
    _ controller: AdaptyFlowController,
    didFinishPurchase product: AdaptyPaywallProduct,
    purchaseResult: AdaptyPurchaseResult
) {
    if !purchaseResult.isPurchaseCancelled {
        controller.dismiss(animated: true)
    }
}

UIKit

AdaptyPaywallController → AdaptyFlowController

コントローラーの型とファクトリーメソッドの名前を変更します:

- let controller = try AdaptyUI.paywallController(
-     with: paywallConfiguration,
-     delegate: self
- )
+ let controller = try AdaptyUI.flowController(
+     with: flowConfiguration,
+     delegate: self
+ )

AdaptyPaywallControllerDelegate → AdaptyFlowControllerDelegate

プロトコル名を変更し、すべてのメソッドシグネチャを更新してください。didSelectProduct が削除された AdaptyPaywallProductWithoutDeterminingOffer の代わりに AdaptyPaywallProduct を受け取るようになった点、および didFinishPurchase は実装が必須になった点(デフォルト実装がなくなりました)に注意してください。

- class YourClass: AdaptyPaywallControllerDelegate {
+ class YourClass: AdaptyFlowControllerDelegate {

-     func paywallControllerDidAppear(_ controller: AdaptyPaywallController) { }
+     func flowControllerDidAppear(_ controller: AdaptyFlowController) { }

-     func paywallControllerDidDisappear(_ controller: AdaptyPaywallController) { }
+     func flowControllerDidDisappear(_ controller: AdaptyFlowController) { }

-     func paywallController(_ controller: AdaptyPaywallController,
-                            didPerform action: AdaptyUI.Action) { }
+     func flowController(_ controller: AdaptyFlowController,
+                         didPerform action: AdaptyUI.Action) { }

-     func paywallController(_ controller: AdaptyPaywallController,
-                            didSelectProduct product: AdaptyPaywallProductWithoutDeterminingOffer) { }
+     func flowController(_ controller: AdaptyFlowController,
+                         didSelectProduct product: AdaptyPaywallProduct) { }

-     func paywallController(_ controller: AdaptyPaywallController,
-                            didStartPurchase product: AdaptyPaywallProduct) { }
+     func flowController(_ controller: AdaptyFlowController,
+                         didStartPurchase product: AdaptyPaywallProduct) { }

-     func paywallController(_ controller: AdaptyPaywallController,
-                            didFinishPurchase product: AdaptyPaywallProduct,
-                            purchaseResult: AdaptyPurchaseResult) { }
+     func flowController(_ controller: AdaptyFlowController,
+                         didFinishPurchase product: AdaptyPaywallProduct,
+                         purchaseResult: AdaptyPurchaseResult) { }

-     func paywallController(_ controller: AdaptyPaywallController,
-                            didFailPurchase product: AdaptyPaywallProduct,
-                            error: AdaptyError) { }
+     func flowController(_ controller: AdaptyFlowController,
+                         didFailPurchase product: AdaptyPaywallProduct,
+                         error: AdaptyError) { }

-     func paywallControllerDidStartRestore(_ controller: AdaptyPaywallController) { }
+     func flowControllerDidStartRestore(_ controller: AdaptyFlowController) { }

-     func paywallController(_ controller: AdaptyPaywallController,
-                            didFinishRestoreWith profile: AdaptyProfile) { }
+     func flowController(_ controller: AdaptyFlowController,
+                         didFinishRestoreWith profile: AdaptyProfile) { }

-     func paywallController(_ controller: AdaptyPaywallController,
-                            didFailRestoreWith error: AdaptyError) { }
+     func flowController(_ controller: AdaptyFlowController,
+                         didFailRestoreWith error: AdaptyError) { }

-     func paywallController(_ controller: AdaptyPaywallController,
-                            didFailRenderingWith error: AdaptyUIError) { }
+     func flowController(_ controller: AdaptyFlowController,
+                         didReceiveError error: AdaptyUIError) { }

-     func paywallController(_ controller: AdaptyPaywallController,
-                            didFailLoadingProductsWith error: AdaptyError) -> Bool { }
+     func flowController(_ controller: AdaptyFlowController,
+                         didFailLoadingProductsWith error: AdaptyError) -> Bool { }

-     func paywallController(_ controller: AdaptyPaywallController,
-                            didPartiallyLoadProducts failedIds: [String]) { }
+     func flowController(_ controller: AdaptyFlowController,
+                         didPartiallyLoadProducts failedIds: [String]) { }

-     func paywallController(_ controller: AdaptyPaywallController,
-                            didFinishWebPaymentNavigation product: AdaptyPaywallProduct?,
-                            error: AdaptyError?) { }
+     func flowController(_ controller: AdaptyFlowController,
+                         didFinishWebPaymentNavigation product: AdaptyPaywallProduct?,
+                         error: AdaptyError?) { }
 }

SwiftUI

.paywall() モディファイア → .flow()

モディファイアの名前を変更し、設定パラメータ名を更新して、必須となった didFinishPurchase クロージャを追加します。

 @State var flowPresented = false // rename freely — the variable name is your choice

 var body: some View {
     Text("Hello, AdaptyUI!")
-        .paywall(
+        .flow(
             isPresented: $flowPresented,
-            paywallConfiguration: paywallConfiguration,
+            flowConfiguration: flowConfiguration,
+            didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ },
             didFailPurchase: { product, error in /* handle the error */ },
             didFinishRestore: { profile in /* check access level and dismiss */ },
             didFailRestore: { error in /* handle the error */ },
-            didFailRendering: { error in flowPresented = false }
+            didReceiveError: { error in flowPresented = false }
         )
 }

名前が変更されたコールバックは、didFailRendering が対応していたのと同じレンダリングエラーに加え、フロースクリプトの新しいランタイムエラー(AdaptyUIError コード 4105 — .jsException の JavaScript 例外)にも対応します。既存のハンドラー本体はコードを変更する必要はありません。パラメーターの名前を変更するだけです。

AdaptyPaywallView → AdaptyFlowView

ビューの名前を変更し、設定パラメータを更新し、現在必須となった didFinishPurchase クロージャを追加して、didSelectProduct クロージャを更新してください。このクロージャは、削除された AdaptyPaywallProductWithoutDeterminingOffer の代わりに AdaptyPaywallProduct を受け取るようになりました。

- AdaptyPaywallView(
-     paywallConfiguration: paywallConfiguration,
-     didSelectProduct: { product: AdaptyPaywallProductWithoutDeterminingOffer in /* handle */ },
+ AdaptyFlowView(
+     flowConfiguration: flowConfiguration,
+     didSelectProduct: { product: AdaptyPaywallProduct in /* handle */ },
+     didFinishPurchase: { product, purchaseResult in /* dismiss, or do nothing to let the flow continue */ },
     didFailPurchase: { product, error in /* handle the error */ },
     didFinishRestore: { profile in /* check access level and dismiss */ },
     didFailRestore: { error in /* handle the error */ },
-    didFailRendering: { error in /* handle the error */ }
+    didReceiveError: { error in /* handle the error */ }
 )

AdaptyUI カスタムアセット

AdaptyUICustomVideoAsset

既存のすべての呼び出し箇所に影響する変更が2点あります。

  • .player が AVQueuePlayer の代わりに AVPlayer を受け取るようになりました。
  • すべてのケースに末尾の resolution: CGSize? パラメータが追加されました。現在の動作を維持するには nil を渡してください。動画が読み込まれる前にプレイヤーがレイアウトスペースを確保できるよう(アスペクト比 = width / height)、実際のピクセルサイズを渡すこともできます。
- case file(url: URL, preview: AdaptyUICustomImageAsset?)
- case remote(url: URL, preview: AdaptyUICustomImageAsset?)
- case player(item: AVPlayerItem, player: AVQueuePlayer, preview: AdaptyUICustomImageAsset?)
+ case file(url: URL, preview: AdaptyUICustomImageAsset?, resolution: CGSize?)
+ case remote(url: URL, preview: AdaptyUICustomImageAsset?, resolution: CGSize?)
+ case player(item: AVPlayerItem, player: AVPlayer, preview: AdaptyUICustomImageAsset?, resolution: CGSize?)

アトリビューションと連携識別子

updateAttribution(_:source:)

source パラメーターの型が String から新しい AdaptyAttributionSource 型に変更され、以前はネストされていた AdaptyProfile.AttributionSource がトップレベルの AdaptyAttributionSource に改名されました。定義済みのソースを使用するか、その他のソースには文字列リテラルを渡してください。AdaptyAttributionSource は ExpressibleByStringLiteral に準拠しているため、既存の文字列リテラルによる呼び出しはそのままコンパイルできます。

- try await Adapty.updateAttribution(attribution, source: "adjust")
+ try await Adapty.updateAttribution(attribution, source: .adjust)

定義済みソース: .appleAds、.adjust、.appsflyer、.branch、.tenjin。ソースを String 変数で保持している場合は、AdaptyAttributionSource(rawValue: yourSource) でラップしてください。

Note

SDK 4.1 ではこのメソッドが updateExternalAttribution(_:provider:) に、型が AdaptyExternalAttributionProvider に改名されました。古い名前は 4.1 で非推奨なしに削除されています。4.1 へ直接移行する場合は v4.1 への移行 を参照してください。

setIntegrationIdentifier(_:)

setIntegrationIdentifier(key:value:) は、1つ以上の AdaptyIntegrationIdentifier 値を受け取る可変長引数メソッドに置き換えられました。生の文字列キーの代わりに、定義済みのファクトリーメソッドを使用してください:

- try await Adapty.setIntegrationIdentifier(key: "appsflyer_id", value: uid)
+ try await Adapty.setIntegrationIdentifier(.appsflyerId(uid))

1回の呼び出しで複数の識別子を設定できます:

try await Adapty.setIntegrationIdentifier(
    .appsflyerId(uid),
    .adjustDeviceId(adid)
)

各古いキー文字列をそのファクトリーメソッドに置き換えます:

v3 キーv4 ファクトリー
"adjust_device_id".adjustDeviceId(_:)
"airbridge_device_id".airbridgeDeviceId(_:)
"amplitude_user_id".amplitudeUserId(_:)
"amplitude_device_id".amplitudeDeviceId(_:)
"appmetrica_device_id".appmetricaDeviceId(_:)
"appmetrica_profile_id".appmetricaProfileId(_:)
"appsflyer_id".appsflyerId(_:)
"branch_id".branchId(_:)
"facebook_anonymous_id".facebookAnonymousId(_:)
"firebase_app_instance_id".firebaseAppInstanceId(_:)
"mixpanel_user_id".mixpanelUserId(_:)
"one_signal_subscription_id".oneSignalSubscriptionId(_:)
"one_signal_player_id".oneSignalPlayerId(_:)
"posthog_distinct_user_id".posthogDistinctUserId(_:)
"pushwoosh_hwid".pushwooshHWID(_:)
"tenjin_analytics_installation_id".tenjinAnalyticsInstallationId(_:)