Skip to content

Add a SwiftUI paywall example for every subscription state - #13

Merged
Ramiz69 merged 1 commit into
mainfrom
example/paywall-demo
Oct 19, 2026
Merged

Ramiz69 merged 1 commit into
mainfrom
example/paywall-demo

Conversation

@Ramiz69

@Ramiz69 Ramiz69 commented Oct 19, 2026

Copy link
Copy Markdown
Owner

What

Examples/PaywallDemo is an iOS app showing a paywall that reacts to the five subscription states StoreKit 2
reports: subscribed, grace period, billing retry, expired (with its reason) and revoked. It goes with the
article on subscription states. It also tours the public API: subscriptionStatus(inGroup:),
subscriptionStatusUpdates, PurchaseOptions with win-back and promotional offers,
catch PurchasesError.purchaseCancelled, and showManageSubscriptions(in:).

New customer Grace period Billing retry Expired → win-back
  • Demo mode switches between live StoreKit and every state through a PurchasesProtocol stand-in built
    from public initializers. The stand-in also drives a SwiftUI preview per state.
  • Live mode runs against PaywallDemo.storekit via the scheme, so no App Store Connect setup is needed.
    Grace period and billing retry can be reproduced through Debug → StoreKit → Manage Transactions.
  • The project uses the Xcode 26.3 format (objectVersion = 100). It is the newest format the CI's Xcode 26.6
    opens.
  • CI gains one step that builds the example.

The package itself is unchanged: Examples/ is not part of any target, so no release is needed.

Verified

  • xcodebuild build -project Examples/PaywallDemo/PaywallDemo.xcodeproj -scheme PaywallDemo -destination generic/platform=iOS\ Simulator CODE_SIGNING_ALLOWED=NO
    succeeds with no warnings from the example's sources (Xcode 27.1).
  • swift build and swift test of the package still pass (97 tests).
  • The demo was checked in an iOS 27 simulator in light and dark mode.
  • When launched outside Xcode, live mode loads no products, since only Xcode's Run action applies the
    StoreKit file. The app then shows an empty state that offers demo mode instead of a blank screen.

Examples/PaywallDemo is a small iOS app that shows what the subscription
status API is for: a paywall that does not pitch "Unlock Premium" to a customer
whose card was just declined.

- Grace period: access stays, and the screen asks for a payment-method update
  before the date access would end.
- Billing retry: Premium is on hold rather than for sale. The plans are hidden
  and the main action opens the subscription settings, so nobody is sold a
  second subscription while they still have one.
- Expired with auto-renew turned off gets the win-back offer. Expired after a
  billing error gets the promotional offer. Revoked means access is gone.

Demo mode switches between live StoreKit and each of these states, using a
stand-in built from the models' public initializers. A reader can see every
state in a minute without Xcode's transaction manager, and the stand-in doubles
as an example of mocking PurchasesProtocol. The same stand-in drives a SwiftUI
preview for each state.

The scheme's Run action uses PaywallDemo.storekit, so the app runs with no App
Store Connect setup. The file defines monthly and yearly plans with a trial, a
promotional and a win-back offer, a consumable and a lifetime unlock.

The project uses the Xcode 26.3 format (objectVersion 100). It is the newest
format the CI's Xcode 26.6 can open, and it matches the package's OS 26 floor.
CI builds the example so it cannot fall behind the kit's API.
@Ramiz69
Ramiz69 merged commit b6448d3 into main Oct 19, 2026
1 check passed
@Ramiz69
Ramiz69 deleted the example/paywall-demo branch October 19, 2026 14:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant