Configuring Subscriptions using RevenueCat (Part 1: RevenueCat)

Mark
Posted: Dec 22nd, 2025
By: Mark

Since the last time I set up RevenueCat, the company released Test Store, a feature that allows you to start building out your subscriptions without having to set anything up in App Store Connect. This has made things a whole lot easier than it used to be.

Creating the Project

The first thing is to create a new project. On the RevenueCat Home Page, click on the All projects dropdown in the upper left hand corner and click on Create a new project.

Create Project Create a Project

Give your project a name, select the category, and choose the platforms that you want to support.

Create Offerings Configure the project

Next, you need to configure the products that you wish to sell. You should configure these to be the same offerings that you plan to use in production. The entitlement name should match what you plan to use as the Subscription Group name.

Install the SDK Create Offerings

The final screen provides information on how to install the SDK and provides examples on how to add the information to your app.

Install the SDK Install the SDK

Create the Paywall

One your application is configured in RevenueCat, the next step is to create the Paywall. You can start by clicking Paywalls in the left side menu and then clicking New paywall. Browse through the templates and fine the one that best suits your app and update it for your app. You can find documentation and a full tutorial on creating a paywall here.

Create Paywall Create the Paywall

Add RevenueCat to your Application

One you have your paywall configured you can easily add it to your application with just a little bit of code. First is to add the RevenueCat package to your project. You can do this by clicking File -> Add Package Dependencies… and pasting the URL https://github.com/RevenueCat/purchases-ios-spm.git in the search box and then clicking Add Package. You need to make sure that you choose to add RevenueCat and RevenueCatUI to your app target.

Install the SDK Install the SDK

Next, we need to configure the application with the test signing key. Make sure you import RevenueCat to your App file and then add the following:

init() {
    Purchases.configure(withAPIKey: "test_FiDZuWpYGHliuhfGwkAakPANNFqh")
}

The example page gives you a function you can use to check your entitlement, but I prefer to have an entitlement manager that I can reuse throughout the app.

import Foundation
import RevenueCat

@Observable
@MainActor
final class EntitlementManager {
    static let shared = EntitlementManager()

    var hasEntitlement: Bool = false

    private let entitlementID = "BookHaven Pro"  // Update to your entitlement name

    @ObservationIgnored private var updateTask: Task<Void, Never>?

    private init() {
        startListening()
    }

    private func startListening() {
        updateTask = Task { [weak self] in
            guard let self else { return }
            for await customerInfo in Purchases.shared.customerInfoStream {
                let isActive = customerInfo.entitlements[entitlementID]?.isActive == true
                // Updates must happen on the MainActor (guaranteed by @MainActor on the class)
                hasEntitlement = isActive
            }
        }
    }

    // Optional: Manual refresh (e.g., on app foreground or pull-to-refresh)
    func refresh() async {
        do {
            let customerInfo = try await Purchases.shared.customerInfo()
            hasEntitlement = customerInfo.entitlements[entitlementID]?.isActive == true
        } catch {
            print("Error refreshing customer info: \(error)")
        }
    }

    deinit {
        updateTask?.cancel()
    }
}

Now you can use the EntitlementManager on any page where you need to check to see if they are a subscriber by either using it as a singleton

@State private var entitlementManager = EntitlementManager.shared

or by importing it in the App file and using it as an environmental variable

import SwiftUI
import CoreData
import RevenueCat

@main
struct BookHavenApp: App {
    @State private var entitlementManager = EntitlementManager.shared

    let persistenceController = PersistenceController.shared
    

    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(\.managedObjectContext, persistenceController.container.viewContext)
                .environment(entitlementManager)
        }
    }
    
    init() {
        Purchases.configure(withAPIKey: "test_evobQqSGYzDHjBilFPxgtHGjNUd")
    }
}

and importing it on the views that need it

@Environment(EntitlementManager.self) private var entitlementManager

Adding the Paywall

Adding the paywall to your views is as simple as importing the RevenueCatUI and then calling the PaywallView(). My preference is to use it as a sheet and present it whenever somebody clicks on a feature that requires a subscription. You can do this by enclosing your functionality in an if statement.

import SwiftUI
import RevenueCatUI

struct PaywallTest: View {
    @Environment(EntitlementManager.self) private var entitlementManager
    @State private var showPaywall: Bool = false

    var body: some View {
        VStack {
            Text("Subscription Test")

            // Check to see if the user is entitled and if not show the subscribe button
            if !entitlementManager.hasEntitlement {
                Button {
                    showPaywall.toggle()
                } label: {
                    Text("Subscribe")
                }
            } else {
                // Actual application work
            }
        }
        .sheet(isPresented: $showPaywall) {
            PaywallView(displayCloseButton: true)
            
        }
    }
}

#Preview {
    PaywallTest()
        .environment(EntitlementManager.shared)
}
Tags:
revenuecat bookhaven