iOS Subscription Management with SwiftUI and StoreKit2: A Complete Guide📱
Introduction
In this article, we’ll explore how to implement a subscription management system for iOS apps using SwiftUI and StoreKit2. StoreKit2 is Apple’s new framework that makes it easy to implement in-app purchases and subscriptions. We’ll be using SwiftSubKit, a popular UI library that supports StoreKit2, to create a seamless and modern user experience. 🚀
The icon incorporates the “Liquid Glass” design aligned with the latest iOS 26, which looks great. It’s distinctive and personally appealing. ✨
SwiftSubKit comes with many pre-built color themes. Additionally, you can set custom colors of your choice, making it very convenient.
Final Result
Here’s what our subscription paywall screen will look like. The design is quite rich and polished. ✨
What is a Paywall? A paywall is a system that restricts access to specific content or features on a website or app, requiring users to pay or become premium members to access them.
Development Environment
- Xcode 16.2
- Swift 5
- iOS 18.0
Library Used 🚀
https://www.codemall.jp/product/1
Complete Code Structure
The overall file structure for our tutorial app (with subscription billing) is as follows:
.
├── ContentView.swift // Only one file to implement!
├── MainStoreConfig.storekit
└── TutorialAppApp.swiftTutorialAppApp.swift contains the default content generated when creating a new Xcode project:
import SwiftUI
@main
struct TutorialAppApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}Next, let’s look at ContentView.swift. Normally, you would need to implement subscription state management and StoreKit2 integration yourself, but with SwiftSubKit, these are handled automatically, so developers don't need to implement them individually.
import SwiftUI
import SwiftSubKit
struct ContentView: View {
@State private var showPaywall = false
var body: some View {
NavigationView {
VStack(spacing: 40) {
// Content omitted for brevity
Button {
showPaywall = true
} label: {
HStack {
Text("Show PaywallView")
.fontWeight(.semibold)
}
}
}
.navigationTitle("SwiftSubKit Demo")
.navigationBarTitleDisplayMode(.inline)
}
.sheet(isPresented: $showPaywall) {
// PaywallView configuration example
CardPaywallView(
productIDs: ["sample1", "sample2"],
theme: .instagram,
configuration: PaywallConfiguration(
closeButtonText: "Close",
loadingText: "Loading plans...",
selectPlanButtonText: "Select Plan",
startTrialButtonText: "Start Free Trial",
restorePurchasesText: "Restore Purchases",
cancelAnytimeText: "Cancel Anytime",
termsOfServiceText: "Terms of Service",
privacyPolicyText: "Privacy Policy",
termsOfServiceURL: URL(string: "https://example.com/terms"),
privacyPolicyURL: URL(string: "https://example.com/privacy"),
successTitle: "Welcome to Premium!",
successMessage: "Enjoy your premium features",
getStartedText: "Get Started!"
),
title: "Choose Your Plan",
subtitle: "Swipe to explore options",
features: [
PaywallFeature(title: "Ad-Free Music", description: "Uninterrupted listening", icon: "music.note"),
PaywallFeature(title: "Offline Downloads", description: "Listen anywhere", icon: "arrow.down.circle.fill")
]
)
}
}
}That’s it! The minimum implementation is complete. It’s amazing that you can implement subscription functionality with just this much code. Let’s now explore the various configuration options for PaywallView. ✨
PaywallView Configuration Parameters
Here are the main configuration parameters for PaywallView. With SwiftSubKit, most display elements can be customized.
Parameter: productIDs
Type: [String]
Description: Array of product IDs configured in App Store Connect
Sample Value: [“sample1”, “sample2”]
Parameter: theme
Type: PaywallTheme
Description: Paywall theme design
Sample Value: .instagram
Parameter: configuration
Type: PaywallConfiguration
Description: Detailed configuration options (see below)
Sample Value: -
Parameter: title
Type: String
Description: Main title of the paywall
Sample Value: “Choose Your Plan”
Parameter: subtitle
Type: String
Description: Subtitle of the paywall
Sample Value: “Swipe to explore options”
Parameter: features
Type: [PaywallFeature]
Description: Array of features (see below)
Sample Value: -
PaywallConfiguration Settings
Here are the PaywallConfiguration settings. For subscription Store reviews, terms of service and privacy policy are often required, so make sure to set them properly.
Setting: closeButtonText
Type: String
Description: Close button text
Sample Value: “Close”
Setting: loadingText
Type: String
Description: Loading text
Sample Value: “Loading plans…”
Setting: selectPlanButtonText
Type: String
Description: Plan selection button text
Sample Value: “Select Plan”
Setting: startTrialButtonText
Type: String
Description: Free trial start button text
Sample Value: “Start Free Trial”
Setting: restorePurchasesText
Type: String
Description: Restore purchases button text
Sample Value: “Restore Purchases”
Setting: cancelAnytimeText
Type: String
Description: Cancellation policy text
Sample Value: “Cancel Anytime”
Setting: termsOfServiceText
Type: String
Description: Terms of service link text
Sample Value: “Terms of Service”
Setting: privacyPolicyText
Type: String
Description: Privacy policy link text
Sample Value: “Privacy Policy”
Setting: termsOfServiceURL
Type: URL?
Description: Terms of service URL
Sample Value: URL(string: “https://example.com/terms")
Setting: privacyPolicyURL
Type: URL?
Description: Privacy policy URL
Sample Value: URL(string: “https://example.com/privacy")
Setting: successTitle
Type: String
Description: Purchase success title
Sample Value: “Welcome to Premium!”
Setting: successMessage
Type: String
Description: Purchase success message
Sample Value: “Enjoy your premium features”
Setting: getStartedText
Type: String
Description: Get started button text after purchase
Sample Value: “Get Started!”
PaywallFeature Settings
Here are the PaywallFeature settings. You can display the characteristics of each subscription in a list format.
Setting: title
Type: String
Description: Feature title
Sample Value: “Ad-Free Music”
Setting: description
Type: String
Description: Feature description
Sample Value: “Uninterrupted listening”
Setting: icon
Type: String
Description: SF Symbols icon name
Sample Value: “music.note”Available Theme Examples
SwiftSubKit provides many color themes. You can also set custom colors as needed.
Theme: .default
Description: Clean and modern design. A balanced basic theme suitable for all purposes.
Theme: .dark
Description: Cool theme with dark background and prominent accent colors.
Theme: .minimal
Description: Simple layout focused on text with minimal decoration.
Theme: .netflix
Description: Striking theme based on Netflix’s red color scheme.
Theme: .spotify
Description: Theme based on Spotify’s deep green and black colors.
Theme: .instagram
Description: Visual-focused theme utilizing Instagram-style gradients.
Additional Notes
productIDsshould specify the subscription product IDs configured in App Store Connect- URL parameters (
termsOfServiceURL,privacyPolicyURL) are optional but may be required for App Store review - You can add multiple features in the
featuresarray, and each feature can have SF Symbols icons - All text items support localization
Creating Subscription Products
Once implementation is complete, you’ll want to test the subscription functionality. Apple provides two testing environments for in-app purchases: StoreKit Configuration for local testing and Apple's Sandbox environment.
The typical development flow is to first use StoreKit Configuration for basic functionality testing, then move to the Sandbox environment for more production-like testing once the features are stable.
Let’s look at how to register products in each environment.
StoreKit Configuration
StoreKit Configuration is a test simulation environment that works entirely within Xcode, making it easier to test than the Sandbox environment.
First, from the Xcode menu bar, select “File” > New > File from Template..., then select StoreKit Configuration File from the Other category to create the file.
Select the created file, then click the “+” button in the bottom left and choose Add Auto-Renewable Subscription to add subscription products. You can freely set Product ID, product name, price, subscription duration, etc.
To use the created StoreKit Configuration file, specify it in the StoreKit Configuration field within the Options section of the Scheme’s Run settings.
Now when you launch the app from Xcode with the specified scheme, you’ll be able to purchase the products configured in the StoreKit Configuration file.
Sandbox Environment
The Sandbox environment is Apple’s official testing environment that integrates with App Store Connect, allowing testing in conditions closer to production than StoreKit Configuration.
For testing in an environment closer to production, you’ll use the Sandbox environment. You can create dedicated test accounts from “Sandbox Testers” in the “Users and Access” section of App Store Connect.
When conducting actual purchase tests, simply enter the created Sandbox tester account information in the Apple ID and password dialog that appears during purchase. Of course, no actual charges will occur, so you can test with confidence.
Sandbox accounts are managed completely independently from regular Apple IDs. Once logged in, you can perform the following operations from the App Store section in the device’s Settings app:
- Switch accounts
- Cancel subscriptions
- Check purchase history
The Sandbox environment is valuable when you want to test multi-device functionality that can’t be verified with StoreKit Configuration, or when you want to test experiences closer to actual user scenarios.
Conclusion
How did you find this guide?
In this article, we’ve covered in detail how to implement subscription management for iOS apps using SwiftUI and StoreKit2.
Implementing subscriptions is crucial for monetization and ongoing user support. With SwiftSubKit as introduced in this article, you can easily implement complex billing processes with minimal code. I hope this serves as a helpful reference for implementing billing functionality.