* WIP * Merge branch 'main' into default-tuist-to-local-swift-package * Cleanup * Merge branch 'main' into default-tuist-to-local-swift-package * Fix error with RevenueCatUI * Removes project v3LoadShedderIntegration from tuist integration * Add both CI.xcconfig and Local.xcconfig if they are both available * Remove unnecessary package * Remove purchases-ios as s tuist dependency It's already resolved in Tuist/ProjectDescriptionHelpers/ProjectDescriptionPackages.swift * New tuist project "RevenueCatTests" containing all test targets * Merge branch 'main' into default-tuist-to-local-swift-package * Fix Tuist dependency mode issues and clean up project structure - Use exhaustive switch in ProjectDescriptionPackages instead of if/else if - Extract shared allDestinations/allDeploymentTargets into ProjectDescriptionHelpers (DRY) - Fix duplicate ReceiptParser scheme across RevenueCat and RevenueCatTests projects - Remove stale cross-project test target references from schemes - Fix bundleId typo in BackendCustomEntitlementsIntegrationTests - Restore purchases-ios in Tuist/Package.swift for remoteXcodeProject mode - Make RevenueCat/RevenueCatUI workspace inclusion conditional on dependency mode - Fix BinarySizeTest to use shared dependency helpers instead of removed APIs - Fix misleading doc comments on internal dependency helpers Co-authored-by: Cursor <cursoragent@cursor.com> * Remove and gitignore file * Fix Bundle.module ambiguity in RevenueCatUITests and add explicit scheme Use Bundle.revenueCatUI instead of Bundle.module to resolve ambiguity when both RevenueCat and RevenueCatUI are imported via @testable in SPM modes (each module synthesises its own internal Bundle.module). Add explicit RevenueCatUITests scheme to RevenueCatTests project for proper scheme generation during full tuist generate. Made-with: Cursor * Fix BinarySizeTest localSource deps and remove dead code Revert BinarySizeTest localSource to explicit .project(target:) references — it manages its own integration modes independently of DependencyMode, and the switch to .revenueCat/.revenueCatUI broke it in the default localSwiftPackage mode (no SPM package declared). Remove unused allDeploymentTargets constant from RevenueCatUI project. Made-with: Cursor * Add priority flush with rate limiting and queuing for feature events Priority events (paywall impressions, custom paywall events) now trigger an immediate flush to the backend. A rate limiter (5 calls/60s) prevents excessive network requests from rapid tracking calls. When a priority event arrives during an in-progress flush, it is queued and drained after the current flush completes. * Extract EventsManagerStrings to separate file to fix file length lint * Fix integration tests: use non-priority events for flush tests The `.impression` event now triggers a priority flush, which can consume the event before the test's explicit `flushPaywallEvents` call. Replace with `.cancel` (non-priority) since these tests verify flush mechanics, not event-type behavior. * Fix duplicate RevenueCat targets in localSwiftPackage mode Exclude RevenueCat/RevenueCatUI Tuist projects from the workspace when using localSwiftPackage dependency mode, since the local SPM package already provides these targets. Including both caused "Multiple commands produce" build errors (e.g. in the BinarySizeTest CI job). Also update BinarySizeTest's localSource integration to use SPM package dependencies instead of Tuist project target references, consistent with the workspace no longer including those projects in SPM mode. Made-with: Cursor * Move rate limiter check to drain phase to prevent queued events from exhausting capacity When multiple priority events arrived during an in-progress flush, each one called shouldProceed() on the rate limiter but they all coalesced into a single pending flush. This wasted rate limiter capacity without performing actual flushes. Now the rate limiter is only checked when a flush actually starts in startPendingPriorityFlushIfNeeded(). * Add missing packages declaration to RCTTester project RCTTester uses .revenueCat and .revenueCatUI dependencies which resolve to SPM package products in localSwiftPackage mode, but was missing the packages: .projectPackages declaration needed to provide the package source. Made-with: Cursor * Fix Bundle.module resolution for RevenueCatUI snapshot tests Use #if SWIFT_PACKAGE to select the correct resource bundle in test code: - SPM builds (CI): Bundle.module resolves to the test target's bundle, which contains the test images (header.heic, background.heic) - Tuist builds: Bundle.revenueCatUI resolves to RevenueCatUI's bundle, avoiding ambiguity between multiple Bundle.module definitions Made-with: Cursor * Remove internal jwsRepresentation from ObjC API tester jwsRepresentation is @objc internal on StoreTransaction — it is not part of the public API (absent from .swiftinterface files). Previously this compiled because Tuist framework targets expose internal @objc members in the generated -Swift.h header, but SPM packages only expose public members. Made-with: Cursor * Revert "Merge remote-tracking branch 'origin/rickvdl/priority-flush-events' into default-tuist-to-local-swift-package" This reverts commitaa585aa9c2, reversing changes made to7d10a496ad. * Restore BinarySizeTest localSource to use Xcode project targets localSource now uses .project(target:path:) like on main, with TUIST_RC_XCODE_PROJECT=true set in CI so the workspace includes the RevenueCat/RevenueCatUI projects. spm uses local SPM package refs. Added documentation explaining why BinarySizeTest manages its own dependency integration independently of Environment.dependencyMode. Made-with: Cursor --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Facundo Menzella <facumenzella@users.noreply.github.com> Co-authored-by: Rick van der Linden <rick.vanderlinden@revenuecat.com>
Magic Weather iOS - RevenueCat Sample
Magic Weather is a sample app demonstrating the proper methods for using RevenueCat's Purchases SDK. This sample uses only native platform components - no third-party SDKs other than the Purchases SDK.
Sign up for a free RevenueCat account here.
Requirements
This sample uses:
- Xcode 15.3
- iOS 15
- Swift 5
See minimum platform version requirements for RevenueCat's Purchases SDK here.
Features
| Feature | Sample Project Location |
|---|---|
| 🕹 Configuring the Purchases SDK | Lifecycle/AppDelegate.swift |
| 💰 Building a basic paywall | Controllers/UserViewController.swift |
| 💰 Building a targeted paywall | Controllers/WeatherViewController.swift |
| 🔐 Checking subscription status | Controllers/WeatherViewController.swift |
| 🤑 Restoring transactions | Controllers/UserViewController.swift |
| 👥 Identifying the user | Controllers/UserViewController.swift |
| 🚪 Logging out the user | Controllers/UserViewController.swift |
Setup & Run
Prerequisites
- Be sure to have an Apple Developer Account.
- You must join the Apple Developer Program to create In-App Purchases.
- You must sign the Paid Applications Agreement and complete your bank/tax information to test In-App Purchases.
- Be sure to set up a Sandbox Tester Account for testing purposes.
- Add your App-Specific Shared Secret to RevenueCat. If you don't have a RevenueCat account yet, sign up for free here.
- Be sure to set up at least one subscription on the App Store following our guide and link it to RevenueCat:
- Add the product (e.g.
rc_3999_1y) to RevenueCat's dashboard. It should match the product ID on the App Store. - Attach the product to an entitlement, e.g.
premium. - Attach the product to a package (e.g.
Annual) inside an offering (e.g.saleordefault).
- Add the product (e.g.
- Get your API key from your RevenueCat project.
- Create a Paywall for your default offering.
Steps to Run
-
Download or clone this repository
-
Navigate to the
Examplesdirectory and open the fileMagicWeather.xcodeprojin Xcode. -
On the General tab of the project editor, match the bundle ID to your bundle ID in App Store Connect and RevenueCat.
-
On the Signing & Capabilities tab of the project editor, select the correct development team from the Team dropdown.
-
In the
Constants.swiftfile:- Replace the value for
apiKeywith the API key from your RevenueCat project. - Replace the value for
entitlementIDwith the entitlement ID of your product in RevenueCat's dashboard. - Comment out the error directives.
- Replace the value for
-
Build the app and run it on your device.
Example Flow: Purchasing a Subscription
- On the home page, select Change the Weather.
- On the prompted payment sheet, select the product listed.
- On the next modal, select Subscribe.
- On the next modal, sign in with your Sandbox Apple ID.
- On the next modal, select Ok.
- Return to the home page and select Change the Weather to see the weather change!
Purchase Flow Demo
Support
For more technical resources, check out our documentation.
Looking for RevenueCat Support? Visit our community.