Xcode version requirements and updated deployment targets
purchases-ios v4 requires using Xcode 13.2 or newer. It also updates the minimum deployment targets for iOS, macOS and tvOS.
Minimum deployment targets
v3 | v4 | |
|---|---|---|
iOS | 9.0 | 11.0 |
tvOS | 9.0 | 11.0 |
macOS | 10.12 | 10.13 |
watchOS | 6.2 | 6.2 (unchanged) |
Migration steps
To start us off, our framework name changed from Purchases to Revenue! đ» Youâll now need to explicitly import Revenue instead of Purchases.
1. Update Framework references
Swift
Before | After |
|---|---|
|
|
Objective-C
Before | After |
|---|---|
|
|
1.1 Update Swift Package Manager dependency (if needed)
Select your target in Xcode, then go to Build Phases, and ensure that your targetâs Link Binary with Libraries section references Revenue, and remove the reference to Purchases if it was still there.
Before | After |
|---|---|
|
|
1.2 Update CocoaPods dependency (if needed)
In your Podfile, update the reference to the Pod from Purchases to Revenue.
Before | After |
|---|---|
|
|
1.3 Update Carthage Framework (if needed)
1.3.1 Using XCFrameworks (recommended)
Select your target in Xcode, then go to Build Phases, and ensure that your targetâs Link Binary with Libraries section references Revenue, and remove the reference to Purchases if it was still there. Do the same with the Embed Frameworks section.
Before | After |
|---|---|
|
|
|
|
1.3.2 Using Platform-specific frameworks
We highly recommend moving into XCFrameworks, since these have a simpler setup and prevent compatibility issues with multi-platform setups.
Carthage has a migration guide to move into XCFrameworks available here.
After migrating into XCFrameworks, follow the steps outlined in 1.3.1 to set up the Revenue.
If you canât move into XCFrameworks, you will still need to update the Link Binary with Libraries phase as outlined in 1.3.1 (only using a .framework instead of .xcframework).
After that, update the your input and output for the Run Script phase of Carthage frameworks, replacing Purchases with Revenue.
2. Update code references
2.1 Automatic Migration
When building your project using v4, Xcode should automatically provide one-click fixes methods and types that have been renamed. For the most part, the migration should be doable by just building and applying Xcodeâs automatic fix-its when they pop up.
If you see any issues or new APIs that fix-its didnât cover, weâd appreciate bug reports!
2.2 Update references to `Purchases.foo` to `RevenueCat.foo`
You might run into compilation errors with a message like Error: â_â is not a member type of class âRevenueCat.Purchasesâ`.
The reason is that the class Purchases is no longer the parent of classes such as Offerings. You should reference classes directly or as a child of Revenue, e.g. Revenue instead of Purchases. You can also omit the framework entirely, i.e.: just using Offerings directly.
2.3 Import StoreKit (if needed)
Our V3 SDK automatically imported Store whenever you did import Purchases. Due to Swift limitations, our V4 SDK doesnât do this automatically.
So if youâre referencing StoreKit types directly, you might need to add import Store in Swift, and @import Store in Objective-C.
2.4 Update code to use the new types (if needed)
Step 2.1 should automatically help you convert your code into the new types. See the âNew Typesâ section for more information on what the new types introduce.
2.5 Take advantage of our new APIs
We introduced new features for Customer Support, as well as async/await alternatives for our APIs. These are optional, but could help make your code more readable and easy to maintain.
Some additional changes include:
Updated references of
PurchasertoCustomerto be more consistent across our platformFurther abstraction away from
Storewith new types.Kit
See the âNew APIsâ section of this guide for more details.
New Types
To better support Store, Revenue introduces several new types to encapsulate data from Store and Store:
Store: wraps aProduct StoreorKit .SKProduct StoreKit .Product Store: wraps aTransaction StoreorKit .SKPayment Transaction StoreKit .Transaction Store: wraps aProduct Discount StoreorKit .SKProduct Discount StoreKit .Product .Subscription Offer
These types replace native StoreKit types in all public API methods that used them.
ObjC Changes
Type changes
@import Purchases is now @import Revenue
v3 | v4 |
|---|---|
RCPurchaserInfo | RCCustomerInfo |
RCTransaction | RCStoreTransaction |
RCTransaction.productId | RCStoreTransaction.productIdentifier |
RCTransaction.revenueCatId | RCStoreTransaction.transactionIdentifier |
RCPackage.product | RCPackage.storeProduct |
(RCPurchasesErrorCode).RCOperationAlreadyInProgressError | RCOperationAlreadyInProgressForProductError |
RCPurchasesErrorDomain | RCPurchasesErrorCodeDomain |
RCBackendError | REMOVED |
RCErrorUtils | REMOVED |
RCBackendErrorDomain | REMOVED |
RCFinishableKey | REMOVED |
RCReceivePurchaserInfoBlock | REMOVED |
RCReceiveIntroEligibilityBlock | REMOVED |
RCReceiveOfferingsBlock | REMOVED |
RCReceiveProductsBlock | REMOVED |
RCPurchaseCompletedBlock | REMOVED |
RCDeferredPromotionalPurchaseBlock | REMOVED |
RCPaymentDiscountBlock | REMOVED |
RCPaymentModeNone | REMOVED |
PurchasesDelegate
v3 | v4 |
|---|---|
purchases:didReceiveUpdatedPurchaserInfo: | purchases:didReceiveUpdatedCustomerInfo: |
API changes
v3 | v4 |
|---|---|
purchaserInfoWithCompletion: | getCustomerInfoWithCompletion: |
invalidatePurchaserInfoCache | invalidateCustomerInfoCache |
Purchases -restoreTransactionsWithCompletion: | Purchases -restorePurchasesWithCompletion: |
Purchases -offeringsWithCompletion: | Purchases -getOfferingsWithCompletion: |
Purchases -productsWithIdentifiers:completion: | Purchases -getProductsWithIdentifiers:completion: |
Purchases -paymentDiscountForProductDiscount:product:completion: | REMOVED - Check eligibility for a discount using |
Purchases -purchaseProduct(:discount:) | Purchases -purchaseProduct:withPromotionalOffer:completion: |
Purchases -purchasePackage(:discount:) | Purchases -purchasePackage:withPromotionalOffer:completion: |
Purchases -createAlias: | Purchases -logIn: |
Purchases -identify: | Purchases -logIn: |
Purchases -reset: | Purchases -logOut: |
Swift Changes
Type changes
import Purchases is now import Revenue
v3 | v4 |
|---|---|
Purchases.Offering | |
Purchases.ErrorDomain | See error handling below |
Purchases.ErrorCode.Code | See error handling below |
Purchases.Package | |
Purchases.PurchaserInfo | |
Purchases.Transaction | |
Purchases.Transaction.productId | |
Purchases.Transaction.revenueCatId | |
Purchases.EntitlementInfo | |
Purchases.EntitlementInfos | |
Purchases.PeriodType | |
Purchases.Store | |
RCPurchaseOwnershipType | |
RCAttributionNetwork | |
RCIntroEligibility | |
RCIntroEligibilityStatus | |
RCPaymentMode | |
RCPaymentModeNone | REMOVED |
Purchases.LogLevel | |
Purchases.Offerings | |
Purchases.PackageType | |
Purchases.Errors | |
Purchases.ErrorCode | |
Package.product | |
Package.product.price: NSDecimalNumber |
|
Package.localizedIntroductoryPriceString: String |
|
RCDeferredPromotionalPurchaseBlock | |
Purchases.PurchaseCompletedBlock | |
Purchases.ReceivePurchaserInfoBlock | REMOVED |
Purchases.ReceiveOfferingsBlock | REMOVED |
Purchases.ReceiveProductsBlock | REMOVED |
Purchases.PaymentDiscountBlock | REMOVED |
Purchases.RevenueCatBackendErrorCode | REMOVED |
Purchases.ErrorCode.operationAlreadyInProgressError | |
Purchases.ErrorUtils | REMOVED |
ReadableErrorCodeKey | REMOVED |
RCFinishableKey | REMOVED |
API changes
v3 | v4 |
|---|---|
invalidatePurchaserInfoCache | |
logIn(_ appUserId:, _ completion:) | |
createAlias(_ alias:, _ completion:) | |
identify(_ appUserID:, _ completion:) | |
reset(completion:) | |
purchaserInfo(_ completion:) | |
offerings(_ completion:) | |
products(_ productIdentifiers:, _ completion:) | |
purchaseProduct(_ product:, _ completion:) | |
purchasePackage(_ package:, _ completion:) | |
restoreTransactions(_ completion:) | |
syncPurchases(_ completion:) | |
paymentDiscount(for:product:completion:) | REMOVED - Get eligibility for a discount using |
purchaseProduct(:discount:) | |
purchasePackage(:discount:) |
PurchasesDelegate
v3 | v4 |
|---|---|
purchases(_ purchases: Purchases, didReceiveUpdated purchaserInfo: PurchaserInfo) |
Error handling
Prior to the Swift migration, Purchases exposed errors as NSErrors, so one could detect errors like this:
if error.domain == Purchases.ErrorDomain {
switch Purchases.ErrorCode(_nsError: error).code {
case .purchaseInvalidError: break
default: break
}
}Starting from Version 4, this becomes much simpler:
if let error = error as? RevenueCat.ErrorCode {
switch error {
case .purchaseInvalidError: break
default: break
}
} else {
// Error is a different type
}New APIs
All applicable methods have an async/await alternative.
show: Use this method to show the subscription management for the current user. Depending on where they made the purchase and their OS version, this might take them to theManage Suscriptions(completion:) management, or open the iOS Subscription Management page.URL begin: Use this method to begin a refund request for the purchase that granted the current entitlement.Refund Request For Current Entitlement begin: Use this method to begin a refund request for a purchase, specifying the product identifier.Refund Request(for Product:) begin: Use this method to begin a refund request for a purchase, specifying the entitlement identifier.Refund Request(for Entitlement:) You can now use
customerto be notified whenever thereâs newInfo Stream Customeravailable, as an alternative toInfo purchases(_:.received Updated:)
Reporting undocumented issues:
Feel free to file an issue! New RevenueCat Issue.
Known Issues
ObjC + SPM
If you expose any Purchases objects from one target to another (see example project for what this could look like), that second target will not build due to a missing autogenerated header. Currently there is a known bug in SPM whereby Xcode either doesnât pass the RevenueCat ObjC generated interface to SPM, or SPM just doesnât integrate it. You can follow along: SR-15154.
Workaround:
You must manually add the autogenerated file we committed to the repository RevenueCat-Swift.h to your project, and #import Revenue in your bridging header. You can see how we do this in our SPMIntegration project.





