Created
November 25, 2024 15:31
-
-
Save codykerns/bd385073cdca852310f30e560e1b7cc0 to your computer and use it in GitHub Desktop.
Display a different RevenueCat paywall based on current size class in SwiftUI
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // | |
| // OfferingDecider.swift | |
| // | |
| // Created by Cody Kerns on 11/25/24. | |
| // | |
| import Foundation | |
| import SwiftUI | |
| import RevenueCat | |
| import RevenueCatUI | |
| /// In the RevenueCat dashboard, add an Offering Metadata key for an alternative offering identifier to present if the size class isn't compact | |
| /// e.g. | |
| /// { | |
| /// "alternative_offering_id": "my_other_offering_identifier" | |
| /// } | |
| struct OfferingDecider { | |
| static func getOffering(for sizeClass: UserInterfaceSizeClass?) async -> Offering? { | |
| do { | |
| let offerings: Offerings = try await Purchases.shared.offerings() | |
| // if there isn't an offering configured, return nil | |
| guard let currentOffering = offerings.current else { return nil } | |
| // if the size class is compact, return the standard offering | |
| guard sizeClass == .regular else { return offerings.current } | |
| if let alternativeOfferingId = currentOffering.metadata["alternative_offering_id"] as? String { | |
| // if there's an alt offering id set in metadata, return the offering with that id | |
| // if it's nil, return the current offering | |
| return offerings.all[alternativeOfferingId] ?? currentOffering | |
| } else { | |
| // no alternative id set, just return the current offering | |
| return currentOffering | |
| } | |
| } catch let err { | |
| print("Error fetching offerings: \(err)") | |
| return nil | |
| } | |
| } | |
| } | |
| class ExampleViewModel: ObservableObject { | |
| @State | |
| var shouldDisplayPaywall = false | |
| var paywallOffering: Offering? = nil | |
| func displayPaywall(for sizeClass: UserInterfaceSizeClass? = nil) { | |
| Task { | |
| if let offering = await OfferingDecider.getOffering(for: sizeClass) { | |
| paywallOffering = offering | |
| shouldDisplayPaywall = true | |
| } | |
| } | |
| } | |
| } | |
| struct ExampleView: View { | |
| @StateObject var viewModel: ExampleViewModel | |
| @Environment(\.horizontalSizeClass) private var horizontalSizeClass | |
| var body: some View { | |
| List { | |
| Button("Show Paywall") { | |
| viewModel.displayPaywall(for: horizontalSizeClass) | |
| } | |
| } | |
| .sheet(isPresented: $viewModel.shouldDisplayPaywall) { | |
| if let paywallOffering = viewModel.paywallOffering { | |
| PaywallView(offering: paywallOffering) | |
| } else { | |
| PaywallView() | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment