Native iOS SDK · Swift 5.9+ · SPM
Native Swift Paywalls with 0 ms Latency.
Design and configure paywalls remotely in the MySuperWall dashboard. The native Swift SDK evaluates rules locally on the device and displays dynamic paywalls with zero network wait.
handleTrigger in any View or ControlleronPurchase); you execute the purchase natively with StoreKit 2 or RevenueCat.Quick start
Add the package in Xcode, initialize, and trigger your first paywall:
// AppDelegate.swift or SwiftUI App
import MySuperwall
@main
struct MyApp: App {
init() {
MySuperwall.initialize(appKey: "YOUR_APP_KEY")
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
// In your UIViewController or SwiftUI Representable
MySuperwall.shared.handleTrigger(
presentingController: self,
triggerKey: "onboarding_finish",
onPurchase: { productId in
Task {
// Run native StoreKit 2 purchase
let result = try await Product.purchase(productId)
}
},
onRestore: {
// Restore purchases
},
onDismiss: {
print("Paywall closed")
}
)
Install the SDK
Install version 1.2.0 or later through Swift Package Manager. CocoaPods is not available yet.
Open guided setup · GitHub / SPM
// Xcode → File → Add Package Dependencies
// URL: https://github.com/Unevenn/mysuperwall-ios
// Up to Next Major Version: 1.2.0
// Add MySuperwall to your app target.
// Package.swift:
.package(url: "https://github.com/Unevenn/mysuperwall-ios", from: "1.2.0")
// Target dependency:
.product(name: "MySuperwall", package: "mysuperwall-ios")Initialize
Call MySuperwall.initialize once at app launch:
import MySuperwall
MySuperwall.initialize(
appKey: "YOUR_APP_KEY",
userId: "optional_user_id" // Auto-generated UUID if omitted
)
| Parameter | Default | Description |
|---|---|---|
appKey | nil | Your dashboard app key (or matches bundle ID automatically). |
userId | auto | Persistent user ID. If omitted, stored securely in UserDefaults. |
baseUrl | https://mysuperwall.com/ | Endpoint URL (defaults to production). |
Load store prices and prepare the paywall
After initialization, fetch real products from your existing billing provider and build localizedProducts keyed by exact product ID. Values must include displayPrice, priceString and currencyCode; include derived period prices when used. The snippet shows the SDK call, not a complete billing adapter. Wait for successful price and paywall loading before enabling the entry point. Currency follows the store account; it is not converted from device language. Do this once at startup and again only when prices or the language change: new prices or a new locale before every presentation discard the prepared paywall and make each opening slow.
MySuperwall.shared.setProductData(localizedProducts) { result in
// Check successful manifest loading; enable UI on the main thread.
}Show a Paywall
Trigger a paywall with zero network latency:
MySuperwall.shared.handleTrigger(
presentingController: self,
triggerKey: "premium_feature",
metadata: ["source": "settings_cell"],
onPurchase: { productId in
// Handle IAP
},
onRestore: {
// Handle restore
},
onDismiss: {
// Handle dismiss
}
)
Handle Purchases with StoreKit 2
import StoreKit
MySuperwall.shared.handleTrigger(
presentingController: self,
triggerKey: "pro_upgrade",
onPurchase: { productId in
Task {
guard let product = try? await Product.products(for: [productId]).first else { return }
let result = try? await product.purchase()
switch result {
case .success(let verification):
// Transaction verified!
break
case .userCancelled, .pending, .none:
break
}
}
}
)
User Attributes & Targeting
Set custom audience attributes for in-app rule targeting:
// Set persistent attributes
MySuperwall.shared.setUserAttributes([
"tier": "gold",
"level": 25,
"isSubscriber": false
])
// Identify user across devices
MySuperwall.shared.identify(userId: "user_98765")
Push notifications (optional)
Send notifications from the dashboard through your own Firebase project, for example a reminder after someone closes the paywall that opens a discount paywall. The SDK has no Firebase dependency: your app reads the FCM token and hands it over.
Requires iOS SDK 1.5.0 or later.
- Connect Firebase. In the dashboard open Integrations → Push notifications and upload a Firebase service account key (role: Firebase Cloud Messaging Admin).
- Register the device. After the user allows notifications, pass the FCM token to the SDK, and again whenever it refreshes. It is registered for the current user and language, and again by itself when you change either.
- Handle taps. Give the notification data to the SDK when the user taps it. It reports the tap and returns the trigger to open, so a discount trigger shows your offer.
- Create a notification. In the dashboard open Notifications, choose when to send (for example after the paywall was closed), write the text per language and pick the trigger each reminder opens.
// Token: after the user allowed notifications (Firebase iOS SDK)
Messaging.messaging().token { token, _ in
if let token { MySuperwall.shared.setPushToken(token) }
}
// MessagingDelegate: called again when the token refreshes
func messaging(_ messaging: Messaging, didReceiveRegistrationToken token: String?) {
if let token { MySuperwall.shared.setPushToken(token) }
}
// UNUserNotificationCenterDelegate: the user tapped a notification
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler done: @escaping () -> Void) {
MySuperwall.shared.handleNotificationOpened(
presentingController: topViewController(),
userInfo: response.notification.request.content.userInfo)
done()
}
// Stop notifications (logout, or the user turned them off):
MySuperwall.shared.clearPushToken()
Each device gets the text for its language (the SDK locale); devices without a matching language get the default one. Someone who just bought is skipped, and a purchase cancels pending notifications. Translating the text with DeepL is a Premium feature.
iOS: enable the Push Notifications capability and the Remote notifications background mode, and upload your APNs key in the Firebase console (Project settings → Cloud Messaging).
0 ms Offline Cache & Local Rule Engine
The iOS SDK downloads your app's rules and paywall templates manifest to UserDefaults on cold start. When handleTrigger is called, the LocalRuleEngine evaluates A/B test variants, semantic app versions, and audience rules directly in memory within <1 ms with zero network latency.
API Reference
| Method | Description |
|---|---|
MySuperwall.initialize(...) | Initializes SDK, loads disk manifest into RAM, starts background sync. |
MySuperwall.shared.handleTrigger(...) | Evaluates rules in memory and presents paywall over UIViewController. |
MySuperwall.shared.resolveTrigger(...) | Resolves PaywallResult without displaying UI. |
MySuperwall.shared.identify(...) | Sets authenticated user ID. |
MySuperwall.shared.setUserAttributes(...) | Sets custom metadata for audience targeting. |
setPushToken(_:) | Register the FCM token for this device |
clearPushToken() | Stop notifications for this device |
trackNotificationOpened(userInfo:) | Report a notification tap and get the trigger to open |
handleNotificationOpened(presentingController:userInfo:...) | Report the tap and show the notification's paywall |
MySuperWall iOS Swift SDK · © 2026