PaywallPresentationHandler
A handler class that provides status updates for paywall presentation in register() calls.
Use this handler when you need fine-grained control over paywall events for a specific register() call, rather than global events via SuperwallDelegate.
This handler is specific to the individual register() call. For global paywall events across your app, use SuperwallDelegate instead.
Starting in iOS SDK 4.17.0, PaywallInfo.isLocal indicates whether the paywall was served from a local superwall dev server. Check it in a presentation callback when your app needs to distinguish local previews from dashboard paywalls.
Purpose
Provides callbacks for paywall lifecycle events when using register() with a specific handler instance.
Signature
@objcMembers
public final class PaywallPresentationHandler: NSObject {
public func onPresent(_ handler: @escaping (PaywallInfo) -> Void)
public func onWillDismiss(_ handler: @escaping (PaywallInfo, PaywallResult) -> Void)
public func onDismiss(_ handler: @escaping (PaywallInfo, PaywallResult) -> Void)
public func onSkip(_ handler: @escaping (PaywallSkippedReason) -> Void)
public func onError(_ handler: @escaping (Error) -> Void)
public func onCustomCallback(_ handler: @escaping (CustomCallback) async -> CustomCallbackResult)
}Parameters
Prop
Type
Returns / State
Each method returns Void and configures the handler for the specific paywall lifecycle event.
Usage
Basic handler setup:
func registerFeatureWithHandler() {
let handler = PaywallPresentationHandler()
handler.onPresent { paywallInfo in
print("Paywall presented: \(paywallInfo.id)")
if paywallInfo.isLocal {
print("This paywall came from the local dev server")
}
// Pause background tasks, analytics, etc.
}
handler.onWillDismiss { paywallInfo, result in
print("Paywall will dismiss: \(paywallInfo.id)")
// Prepare for dismissal, save state, etc.
}
handler.onDismiss { paywallInfo, result in
print("Paywall dismissed with result: \(result)")
switch result {
case .purchased:
showSuccessMessage()
case .cancelled:
showPromotionalOffer()
case .restored:
updateUIForActiveSubscription()
}
}
Superwall.shared.register(
placement: "premium_feature",
params: ["source": "feature_screen"],
handler: handler
) {
unlockPremiumFeature()
}
}Handle skip and error cases:
let handler = PaywallPresentationHandler()
handler.onSkip { reason in
print("Paywall skipped: \(reason)")
switch reason {
case .userIsSubscribed:
proceedToFeature()
case .holdout:
proceedToFeature()
default:
break
}
}
handler.onError { error in
print("Paywall error: \(error)")
showErrorAlert(error)
}Handle custom callbacks (4.12.10+):
let handler = PaywallPresentationHandler()
handler.onCustomCallback { callback in
print("Custom callback: \(callback.name)")
// Perform your async work based on the callback name
do {
let result = try await performAction(named: callback.name, with: callback.variables)
return .success(data: ["result": result])
} catch {
return .failure(data: ["error": error.localizedDescription])
}
}
Superwall.shared.register(
placement: "premium_feature",
handler: handler
) {
unlockPremiumFeature()
}Method chaining style:
func registerWithChaining() {
let handler = PaywallPresentationHandler()
.onPresent { _ in pauseVideo() }
.onDismiss { _, result in
resumeVideo()
handlePurchaseResult(result)
}
.onError { error in showAlert(error) }
Superwall.shared.register(
placement: "remove_ads",
handler: handler
) {
hideAdsFromUI()
}
}How is this guide?