Migrer le SDK iOS Adapty vers v3.3

Le SDK Adapty 3.3.0 est une version majeure qui apporte des améliorations pouvant nécessiter quelques étapes de migration de votre part.

  1. Renommer Adapty.Configuration en AdaptyConfiguration.
  2. Renommer la méthode getViewConfiguration en getPaywallConfiguration.
  3. Supprimer les paramètres didCancelPurchase et paywall de SwiftUI, et renommer le paramètre viewConfiguration en paywallConfiguration.
  4. Mettre à jour la gestion des achats intégrés promotionnels depuis l’App Store en supprimant le paramètre defermentCompletion de la méthode AdaptyDelegate.
  5. Supprimer la méthode getProductsIntroductoryOfferEligibility.
  6. Mettre à jour les configurations d’intégration pour Adjust, AirBridge, Amplitude, AppMetrica, Appsflyer, Branch, Facebook Ads, Firebase et Google Analytics, Mixpanel, OneSignal, Pushwoosh.
  7. Mettre à jour l’implémentation du mode Observer.

Renommer Adapty.Configuration en AdaptyConfiguration

Mettez à jour le code d’activation du SDK iOS Adapty de la façon suivante :

Renommer la méthode getViewConfiguration en getPaywallConfiguration

Mettez à jour le nom de la méthode pour récupérer la viewConfiguration du paywall :


guard paywall.hasViewConfiguration else {
    //  use your custom logic
    return
}

do {
-    let paywallConfiguration = try await AdaptyUI.getViewConfiguration(
+    let paywallConfiguration = try await AdaptyUI.getPaywallConfiguration(
            forPaywall: paywall
    )
    // use loaded configuration
} catch {
    // handle the error
}

Pour plus de détails sur la méthode, consultez Récupérer la configuration de vue d’un paywall conçu avec le Paywall Builder.

Modifier les paramètres dans SwiftUI

Les mises à jour suivantes ont été apportées à SwiftUI :

  1. Le paramètre didCancelPurchase a été supprimé. Utilisez didFinishPurchase à la place.
  2. La méthode .paywall() n’accepte plus d’objet paywall.
  3. Le paramètre paywallConfiguration remplace le paramètre viewConfiguration.

Mettez à jour votre code comme ceci :

@State var paywallPresented = false

var body: some View {
	Text("Hello, AdaptyUI!")
			.paywall(
          isPresented: $paywallPresented,
-         paywall: <paywall object>,
-         viewConfiguration: <LocalizedViewConfiguration>,
+         paywallConfiguration: <AdaptyUI.PaywallConfiguration>,
          didPerformAction: { action in
              switch action {
                  case .close:
                      paywallPresented = false
                  default:
                      // Handle other actions
                      break
              }
          },
-         didFinishPurchase: { product, profile in paywallPresented = false },
+         didFinishPurchase: { product, purchaseResult in /* handle the result*/ },
          didFailPurchase: { product, error in /* handle the error */ },
          didFinishRestore: { profile in /* check access level and dismiss */  },
          didFailRestore: { error in /* handle the error */ },
          didFailRendering: { error in paywallPresented = false }
-         didCancelPurchase: { product in /* handle the result*/}

      )
}

Mettre à jour la gestion des achats intégrés promotionnels depuis l’App Store

Mettez à jour la façon dont vous gérez les achats intégrés promotionnels depuis l’App Store en supprimant le paramètre defermentCompletion de la méthode AdaptyDelegate, comme indiqué dans l’exemple ci-dessous :

final class YourAdaptyDelegateImplementation: AdaptyDelegate {
    nonisolated func shouldAddStorePayment(for product: AdaptyDeferredProduct) -> Bool {
        // 1a.
        // Return `true` to continue the transaction in your app.

        // 1b.
        // Store the product object and return `false` to defer or cancel the transaction.
        false
    }
    
    // 2. Continue the deferred purchase later on by passing the product to `makePurchase`
    func continueDeferredPurchase() async {
        let storedProduct: AdaptyDeferredProduct = // get the product object from the 1b.
        do {
            try await Adapty.makePurchase(product: storedProduct)
        } catch {
            // handle the error
        }
    }
}

Supprimer la méthode getProductsIntroductoryOfferEligibility

Avant le SDK iOS Adapty 3.3.0, l’objet produit incluait toujours les offres, peu importe si l’utilisateur y était éligible. Vous deviez vérifier manuellement l’éligibilité avant d’utiliser l’offre.

Désormais, l’objet produit n’inclut une offre que si l’utilisateur est éligible. Cela signifie que vous n’avez plus besoin de vérifier l’éligibilité — si une offre est présente, l’utilisateur y est éligible.

Si vous souhaitez tout de même consulter les offres pour les utilisateurs non éligibles, référez-vous à sk1Product et sk2Product.

Mettre à jour la configuration des SDK d’intégrations tierces

À partir du SDK iOS Adapty 3.3.0, nous avons mis à jour l’API publique de la méthode updateAttribution. Auparavant, elle acceptait un dictionnaire [AnyHashable: Any], vous permettant de passer directement des objets d’attribution issus de différents services. Désormais, elle requiert un [String: any Sendable], vous devrez donc convertir les objets d’attribution avant de les passer.

Pour garantir le bon fonctionnement des intégrations avec le SDK iOS Adapty 3.3.0 et les versions ultérieures, mettez à jour vos configurations SDK pour les intégrations suivantes comme décrit dans les sections ci-dessous.

Adjust

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration du SDK pour l’intégration Adjust.

AirBridge

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration du SDK pour l’intégration AirBridge.

 import AirBridge

- let builder = AdaptyProfileParameters.Builder()
-             .with(airbridgeDeviceId: AirBridge.deviceUUID())
-
- Adapty.updateProfile(params: builder.build())

+ do {
+     try await Adapty.setIntegrationIdentifier(
+         key: "airbridge_device_id", 
+         value: AirBridge.deviceUUID()
+     )
+ } catch {
+     // handle the error
+ }

Amplitude

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration du SDK pour l’intégration Amplitude.

 import Amplitude 

- let builder = AdaptyProfileParameters.Builder()
-             .with(amplitudeUserId: Amplitude.instance().userId)
-             .with(amplitudeDeviceId: Amplitude.instance().deviceId)
-
- Adapty.updateProfile(params: builder.build())

+ do {
+     try await Adapty.setIntegrationIdentifier(
+         key: "amplitude_user_id", 
+         value: Amplitude.instance().userId
+     )
+     try await Adapty.setIntegrationIdentifier(
+         key: "amplitude_device_id", 
+         value: Amplitude.instance().deviceId
+     )
+ } catch {
+     // handle the error
+ }

AppMetrica

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration du SDK pour l’intégration AppMetrica.

 import AppMetricaCore
        
- if let deviceID = AppMetrica.deviceID {
-   let builder = AdaptyProfileParameters.Builder()
-     .with(appmetricaDeviceId: deviceID)
-     .with(appmetricaProfileId: "YOUR_ADAPTY_CUSTOMER_USER_ID")
-
-   Adapty.updateProfile(params: builder.build())
- }

+ if let deviceID = AppMetrica.deviceID {
+     do {
+         try await Adapty.setIntegrationIdentifier(
+             key: "appmetrica_device_id", 
+             value: deviceID
+         )
+         try await Adapty.setIntegrationIdentifier(
+             key: "appmetrica_profile_id", 
+             value: "YOUR_ADAPTY_CUSTOMER_USER_ID"
+         )
+     } catch {
+         // handle the error
+     }
+ }

AppsFlyer

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration du SDK pour l’intégration AppsFlyer.

class YourAppsFlyerLibDelegateImplementation {
    // Find your implementation of AppsFlyerLibDelegate 
    // and update onConversionDataSuccess method:
     func onConversionDataSuccess(_ conversionInfo: [AnyHashable : Any]) {
         let uid = AppsFlyerLib.shared().getAppsFlyerUID()

-        Adapty.updateAttribution(
-           conversionInfo.toSendableDict(),
-            source: .appsflyer,
-            networkUserId: uid
-        )
+        Adapty.setIntegrationIdentifier(key: "appsflyer_id", value: uid)
+        Adapty.updateAttribution(conversionInfo, source: "appsflyer")
    }
}

Branch

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration du SDK pour l’intégration Branch.

class YourBranchImplementation {
    func initializeBranch() {
        // Pass the attribution you receive from the initializing method of Branch iOS SDK to Adapty.
        Branch.getInstance().initSession(launchOptions: launchOptions) { (data, error) in
-           if let data = data?.toSendableDict() {
-                Adapty.updateAttribution(data, source: .branch)
-           }
+           if let data {
+               Adapty.updateAttribution(data, source: "branch")
+           }
        }
    }
}

Facebook Ads

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration du SDK pour l’intégration Facebook Ads.

 import FacebookCore

- let builder = AdaptyProfileParameters.Builder()
-     .with(facebookAnonymousId: AppEvents.shared.anonymousID)
-
- do {
-     try Adapty.updateProfile(params: builder.build())
- } catch {
-     // handle the error
- }

+ do {
+     try await Adapty.setIntegrationIdentifier(
+         key: "facebook_anonymous_id", 
+         value: AppEvents.shared.anonymousID
+     )
+ } catch {
+     // handle the error
+ }

Firebase et Google Analytics

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration du SDK pour l’intégration Firebase et Google Analytics.

 import FirebaseCore
 import FirebaseAnalytics

 FirebaseApp.configure()
        
- if let appInstanceId = Analytics.appInstanceID() {            
-     let builder = AdaptyProfileParameters.Builder()
-         .with(firebaseAppInstanceId: appInstanceId)
            
-     Adapty.updateProfile(params: builder.build()) { error in
-         // handle error
-     }
- }

+ if let appInstanceId = Analytics.appInstanceID() {            
+     do {
+         try await Adapty.setIntegrationIdentifier(
+             key: "firebase_app_instance_id", 
+             value: appInstanceId
+         )
+     } catch {
+         // handle the error
+     }
+ }

Mixpanel

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration du SDK pour l’intégration Mixpanel.

 import Mixpanel

- let builder = AdaptyProfileParameters.Builder()
-             .with(mixpanelUserId: Mixpanel.mainInstance().distinctId)
-
- do {
-     try await Adapty.updateProfile(params: builder.build())
- } catch {
-     // handle the error
- }

+ do {
+     try await Adapty.setIntegrationIdentifier(
+         key: "mixpanel_user_id", 
+         value: Mixpanel.mainInstance().distinctId
+     )
+ } catch {
+     // handle the error
+ }

OneSignal

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration du SDK pour l’intégration OneSignal.

 // PlayerID (pre-v5 OneSignal SDK)
 // in your OSSubscriptionObserver implementation
 func onOSSubscriptionChanged(_ stateChanges: OSSubscriptionStateChanges) {
     if let playerId = stateChanges.to.userId {
-         let params = AdaptyProfileParameters.Builder()
-             .with(oneSignalPlayerId: playerId)
-             .build()
-
-         Adapty.updateProfile(params:params) { error in
-             // check error
-         }
+         Task {
+             try await Adapty.setIntegrationIdentifier(
+                 key: "one_signal_player_id", 
+                 value: playerId
+             )
+         }
     }
 }

 // SubscriptionID (v5+ OneSignal SDK)
 OneSignal.Notifications.requestPermission({ accepted in
-     let id = OneSignal.User.pushSubscription.id
-
-     let builder = AdaptyProfileParameters.Builder()
-         .with(oneSignalSubscriptionId: id)
-
-     Adapty.updateProfile(params: builder.build())
+     Task {
+         try await Adapty.setIntegrationIdentifier(
+             key: "one_signal_subscription_id", 
+             value: OneSignal.User.pushSubscription.id
+         )
+     }
 }, fallbackToSettings: true)

Pushwoosh

Mettez à jour le code de votre application mobile comme indiqué ci-dessous. Pour l’exemple de code complet, consultez la configuration du SDK pour l’intégration Pushwoosh.

- let params = AdaptyProfileParameters.Builder()
-     .with(pushwooshHWID: Pushwoosh.sharedInstance().getHWID())
-     .build()
-
- Adapty.updateProfile(params: params) { error in
-     // handle the error
- }

+ do {
+     try await Adapty.setIntegrationIdentifier(
+         key: "pushwoosh_hwid", 
+         value: Pushwoosh.sharedInstance().getHWID()
+     )
+ } catch {
+     // handle the error
+ }

Mettre à jour l’implémentation du mode Observer

Mettez à jour la façon dont vous liez les paywalls aux transactions. Auparavant, vous utilisiez la méthode setVariationId pour assigner le variationId. Désormais, vous pouvez inclure le variationId directement lors de l’enregistrement de la transaction via la nouvelle méthode reportTransaction. Consultez l’exemple de code final dans Associer des paywalls à des transactions d’achat en mode Observer.

N’oubliez pas d’enregistrer la transaction via la méthode reportTransaction. Si vous omettez cette étape, Adapty ne reconnaîtra pas la transaction, n’accordera pas les niveaux d’accès, ne l’inclura pas dans les analytics et ne l’enverra pas aux intégrations. Cette étape est indispensable !

- let variationId = paywall.variationId
-
- // There are two overloads: for StoreKit 1 and StoreKit 2
- Adapty.setVariationId(variationId, forPurchasedTransaction: transaction) { error in
-     if error == nil {
-         // successful binding
-     }
- }

+ do {
+     // every time when calling transaction.finish()
+     try await Adapty.reportTransaction(transaction, withVariationId: <YOUR_PAYWALL_VARIATION_ID>)
+ } catch {
+     // handle the error
+ }