Migrate Adapty iOS SDK to v4.1
Adapty iOS SDK 4.1 changes how Adapty Attribution is enabled, renames the external attribution APIs, and changes the fallback file format. It also brings back support for App Store promoted in-app purchases, which were removed in 4.0.
The renamed APIs are a hard break. The old names are removed outright — they aren’t deprecated, and there are no typealiases or @available(renamed:) annotations to bridge them. Code that compiles against 4.0.x will fail to compile on 4.1 until you rename every call site listed below.
Quick reference
| v4.0 | v4.1 |
|---|---|
| Adapty Attribution enabled automatically | Adapty Attribution disabled by default; opt in with .with(adaptyAttributionEnabled: true) |
Adapty.updateAttribution(_:source:) | Adapty.updateExternalAttribution(_:provider:) |
Adapty.updateAttribution(_ attributionJson: String, source:) | Removed from the public API; pass a dictionary instead |
AdaptyAttributionSource | AdaptyExternalAttributionProvider, with a new .custom value |
AdaptyProfile.appliedAttributionSources | AdaptyProfile.appliedExternalAttributionProviders |
AdaptySubscriptionOfferType enum | AdaptySubscriptionOfferType struct; .code removed |
| Fallback file downloaded for 4.0 | New fallback file format; download the file again |
| Promoted in-app purchases not supported | didReceivePromotedPurchase(_:) delegate method and AdaptyPromotedProduct |
Adapty Attribution is disabled by default
In 4.0 and earlier, the SDK registered installs for Adapty Attribution automatically. Starting from 4.1, this is off by default: the SDK doesn’t register installs, and the onInstallationDetailsSuccess and onInstallationDetailsFail delegate callbacks never fire. getCurrentInstallationStatus() returns .notAvailable.
If you use Adapty Attribution, enable it when activating the SDK:
let configurationBuilder = AdaptyConfiguration
.builder(withAPIKey: "YOUR_PUBLIC_SDK_KEY")
+ .with(adaptyAttributionEnabled: true)
If you don’t use Adapty Attribution, no changes are needed.
Renamed external attribution APIs
updateAttribution(:source:) → updateExternalAttribution(:provider:)
The method that passes attribution data from an external provider (Adjust, AppsFlyer, Branch, Tenjin, or a custom one) is renamed, and its source parameter is renamed to provider:
- try await Adapty.updateAttribution(attribution, source: .adjust)
+ try await Adapty.updateExternalAttribution(attribution, provider: .adjust)
The JSON string overload is removed
4.0 accepted attribution data either as a [AnyHashable: Any] dictionary or as a JSON String. In 4.1, only the dictionary overload is public — the JSON string overload is reserved for Adapty’s cross-platform SDKs. Deserialize the JSON before you pass it:
- try await Adapty.updateAttribution(attributionJson, source: .adjust)
+ guard let attribution = try JSONSerialization.jsonObject(
+ with: Data(attributionJson.utf8)
+ ) as? [AnyHashable: Any] else { return }
+ try await Adapty.updateExternalAttribution(attribution, provider: .adjust)
AdaptyAttributionSource → AdaptyExternalAttributionProvider
The type is renamed. The predefined providers keep the same names: .appleAds, .adjust, .appsflyer, .branch, .tenjin. It still conforms to ExpressibleByStringLiteral, so string-literal arguments keep compiling. If you keep the provider in a String variable, wrap it: AdaptyExternalAttributionProvider(rawValue: yourProvider).
4.1 also adds a predefined .custom value for providers Adapty doesn’t integrate with directly. In 4.0 the same value was only available as the string literal "custom".
AdaptyProfile.appliedAttributionSources → appliedExternalAttributionProviders
The profile property that lists attribution providers applied to the profile is renamed. Its element type changes accordingly:
- if profile.appliedAttributionSources.contains(.appleAds) {
+ if profile.appliedExternalAttributionProviders.contains(.appleAds) {
// Apple Ads attribution has been applied
}
AdaptySubscriptionOfferType is now a struct
AdaptySubscriptionOfferType — the type of AdaptySubscriptionOffer.offerType — changes from an enum to a RawRepresentable struct, so the backend can introduce new offer types without an SDK update:
- public enum AdaptySubscriptionOfferType: String, Sendable { ... }
+ public struct AdaptySubscriptionOfferType: Sendable, RawRepresentable, Equatable, Hashable { ... }
This affects your code in three ways:
-
Exhaustive
switchstatements no longer compile. A struct has no fixed set of cases, so the compiler can’t prove a switch is exhaustive. Add adefaultbranch:switch offer.offerType { case .introductory: // ... case .promotional: // ... case .winBack: // ... + default: // handle offer types added later } -
.codeis removed. Offer codes are no longer reported throughAdaptySubscriptionOffer.offerType. Remove anycase .codebranch. See Redeem offer codes in iOS for handling offer codes. -
Codableconformance is dropped. If you encoded or decodedAdaptySubscriptionOfferTypedirectly, persistofferType.rawValue(aString) instead and rebuild the value withAdaptySubscriptionOfferType(rawValue:).
Comparisons against the predefined values are unchanged: .introductory, .promotional, and .winBack still work in == checks and as case patterns.
Fallback files
The fallback file format changed in SDK 4.1. Download the file again from Placements > Fallbacks and bundle it in your app, even if you already downloaded one for 4.0.
This step produces no compile error. If you skip it, the SDK rejects the outdated file and every placement loses its fallback.
App Store promoted in-app purchases return
SDK 4.1 restores support for App Store promoted in-app purchases, which 4.0 removed. This is a new feature, not a migration step: it doesn’t change any 4.0 behavior.
If you migrate from 3.x and used shouldAddStorePayment(for:) with AdaptyDeferredProduct, adopt the new didReceivePromotedPurchase(_:) delegate method with AdaptyPromotedProduct instead. Unlike shouldAddStorePayment, the new method doesn’t return a value: if you don’t implement it, the SDK starts the purchase immediately; to defer the purchase, implement it, store the product, and pass the product to makePurchase later. See In-app purchases from the App Store.
The new mechanism is built on StoreKit 2 and requires iOS 16.4 or later. The 3.x shouldAddStorePayment method worked on earlier iOS versions. On devices below iOS 16.4, didReceivePromotedPurchase never fires and promoted purchases don’t reach your app.