Skip to content

Releases: superwall/Superwall-iOS

3.1.0

05 Jul 04:45
72b26fa
Compare
Choose a tag to compare

Enhancements

  • Adds support for paywalls that include a free trial notification. After starting a free trial, the app checks whether the paywall should notify the user when their trial is about to end. If so, the user will be asked to enable notifications (if they haven't already) before scheduling a local notification. You can add a free trial notification to your paywall from the paywall editor.
  • Adds ability to use device.minutesSince_X, device.hoursSince_X, device.daysSince_X, device.monthsSince_X, and device.yearsSince_X in campaign rules and paywalls, where X is an event name. This can include Superwall events, such as app_open, or your own events.
  • Prints out the Superwall SDK version when the debug logLevel is enabled.
  • Adds removeAllPendingSuperwallNotificationRequests(), removeAllPendingNonSuperwallNotificationRequests(), removeAllDeliveredSuperwallNotifications(), and removeAllDeliveredNonSuperwallNotifications() to UNUserNotificationCenter. You can use these methods to remove your app's notifications without affecting Superwall's local notifications and vice-versa.
  • Updates RevenueCat to the latest version in our RevenueCat example app.

Fixes

  • Fixes a Core Data multi-threading issue when performing a count. If you had enabled Core Data multi-threading assertions in Xcode, this will have caused a crash.
  • Fixes very rare crash when purchasing without a PurchaseController.
  • Reduces reliance on Combine when using register to fix memory management crashes.

3.0.3

22 Jun 10:02
ffc8ee1
Compare
Choose a tag to compare

Fixes

  • Fixes an issue where Superwall events app_launch, app_install, and session_start and deepLink_open weren't working as paywall triggers from a cold start.

3.0.2

16 Jun 07:42
1f16dca
Compare
Choose a tag to compare

Fixes

  • Fixes issues with Xcode 15 and iOS 17.
  • Moves the loading of localizations to only when the debugger is launched, therefore reducing setup time of Superwall.
  • Removes reliance on force unwrapping/force casting as a safety precaution.
  • Moves tracking of free trial start and transaction complete events to a higher priority Task. Before, this was of background priority and would take a while to track.
  • Fix crash when trying to access Superwall.shared.userId.
  • Prices in variables are now rounded down, e.g. 3.999 becomes 3.99, rather than 4.00.
  • Fixes incorrect values for trialPeriodPrice, trialPeriodDailyPrice, trialPeriodWeeklyPrice, trialPeriodMonthlyPrice, trialPeriodYearlyPrice variables.

3.0.1

05 Jun 10:42
d89049b
Compare
Choose a tag to compare

3.0.1

Fixes

  • Fixes bug that prevented Superwall from configuring when SwiftUI users in sandbox mode used the App file's init() to configure Superwall.

3.0.0

04 Jun 09:33
3a1ee4f
Compare
Choose a tag to compare

Welcome to SuperwallKit v3.0, the framework formally known as Paywall!

This update is a major release, containing lots of breaking changes, enhancements and bug fixes. We're excited for you to use it!

We understand that transitions between major SDK releases can become frustrating, so we've made a migration guide to make your life easier. We've also updated our example apps to v3, including RevenueCat+SuperwallKit and Objective-C apps. Finally, we recommend you check out our updated docs.

Breaking Changes

  • Renames the package from Paywall to SuperwallKit.
  • Renames the primary static class for integrating Superwall from Paywall to Superwall.
  • Sets the minimum iOS version to iOS 13.
  • Moves all functions and variables to the shared instance for consistency.
  • Renames preloadPaywalls(forTriggers:) to preloadPaywalls(forEvents:)
  • Renames configure(apiKey:userId:delegate:options:) to configure(apiKey:purchaseController:options:completion:). You can use the completion block to know when Superwall has finished configuring.
  • Removes delegate from configure. You now set the delegate via Superwall.shared.delegate.
  • Changes PaywallOptions to SuperwallOptions. This now clearly defines which of the options are explicit to paywalls vs other configuration options within the SDK.
  • Makes Superwall.shared.options internal so that options must be set in configure.
  • Removes Superwall.trigger(event:) and replaces with register(event:params:handler:feature). This is Superwall's most powerful feature yet. Wrap your features with this method to conditionally show paywalls, lock features and more.
  • Renames Paywall.EventName to SuperwallEvent and removes .manualPresent as a SuperwallEvent.
  • Renames PaywallDelegate to SuperwallDelegate.
  • Superwall now automatically handles all subscription-related logic. However, if you'd still like control (e.g. if you're using RevenueCat), you'll need to implement a PurchaseController and set Superwall.shared.subscriptionStatus yourself whenever the subscription status of the user changes. You pass your PurchaseController to configure(apiKey:purchaseController:options:completion:).
  • Removes isUserSubscribed() from the delegate and replaces this with a published instance variable subscriptionStatus. This is enum that defaults to .unknown on first install and the cached value on subsequent app opens. If you're using a PurchaseController to handle subscription-related logic, you must set subscriptionStatus every time the user's subscription status changes. If you're letting Superwall handle subscription-related logic, this value will be updated with the device receipt.
  • For Objective-C users, this changes the SWKPurchaseController method purchase(product:) to purchase(product:completion:). You call the completion block with the result of the user attempting to purchase a product, making sure you handle all cases of SWKPurchaseResult: .purchased, .cancelled, .pending, failed. When you have a purchasing error, you need to call the completion block with the .failed case along with the error.
  • Changes restorePurchases() to an async function that returns a boolean instead of having a completion block.
  • Removes Paywall.load(identifier:). This was being used to preload a paywall by identifier.
  • Removes .triggerPaywall() for SwiftUI apps. Instead, SwiftUI users should now use the UIKit function Superwall.register().
  • Changes the period and periodly attributes for 2, 3 and 6 month products. Previously, the period would be "month", and the periodly would be "monthly" for all three. Now the period returns "2 months", "quarter", "6 months" and the periodly returns "every 2 months", "quarterly", and "every 6 months".
  • Removes localizationOverride(localeIdentifier:) and replaces it with the SuperwallOption localeIdentifier. You set this on configure.
  • Removes ASN1Swift as a package dependency.
  • Changes free trial logic. Previously we'd look at just the primary product. However, we determing free trial eligibility based on the first product in the paywall that has a free trial available.
  • Changes Objective-C method setUserAttributesDictionary(_:) to setUserAttributes(_:).
  • Adds PaywallInfo to SuperwallDelegate methods WillPresentPaywall(withInfo:), didPresentPaywall(withInfo:), willDismissPaywall(withInfo:) and didDismissPaywall(withInfo:).
  • Renames SuperwallDelegate method didTrackSuperwallEventInfo(_:SuperwallEventInfo) to handleSuperwallEvent(withInfo eventInfo: SuperwallEventInfo) for clarity.
  • Renames SuperwallDelegate methods willOpenURL(url:) and willOpenDeepLink(url:) to paywallWillOpenURL(url:) and paywallWillOpenDeepLink(url:) respectively.
  • Changes the logLevel to be non-optional and introduces a none case to turn off logging.
  • Removes all guides from the SDK documentation. From now on, our online docs provide guides and the SDK documentation is only there as a technical reference.
  • Changes the return type of PurchaseController.restorePurchases() from Bool to RestorationResult.
  • Changes DismissState to PaywallResult.
  • Renamed the PaywallResult case closed to declined.
  • Removes .error(Error) from PaywallSkippedReason in favor of a new PaywallState case .presentationError(Error).
  • Exposes the transactionBackgroundView PaywallOption to Objective-C by making it non-optional and adding a none case in place of setting it to nil.

Enhancements

  • Adds getPaywall(forEvent:params:paywallOverrides:delegate:)! You can use this to request the PaywallViewController to present however you like. Please read our docs to learn more about how to use this.
  • Adds paywall caching. This is enabled on all paywalls by default, however it can be turned off on a case by case basis via the dashboard. With this enhancement, your paywalls will load lightning fast and will reduce network load of your app.
  • You can now pass an IdentityOptions object to identify(userId:options). This should only be used in advanced use cases. By setting the restorePaywallAssignments property of IdentityOptions to true, it prevents paywalls from showing until after paywall assignments have been restored. If you expect users of your app to switch accounts or delete/reinstall a lot, you'd set this when identifying an existing account.
  • Adds Superwall.shared.isLoggedIn to check whether the user is logged in to the SDK or not. This will be true if you've previously called identify(userId:options:). This is added to user properties, which means you can create a rule based on whether the user is logged in vs. whether they're anonymous.
  • Adds a new example app, UIKit+RevenueCat, which shows you how to use Superwall with RevenueCat.
  • Adds a new Objective-C example app UIKit-Objc.
  • Adds an Objective-C-only function removeUserAttributes(_:) to remove user attributes. In Swift, to remove attributes you can pass in nil for a specific attribute in setUserAttributes(_:).
  • Adds getPresentationResult(forEvent:params:). This returns a PresentationResult, which preemptively gets the result of registering an event. This helps you determine whether a particular event will present a paywall in the future.
  • Logs when products fail to load with a link to help diagnose the cause.
  • Adds a published property isConfigured. This is a boolean which you can use to check whether Superwall is configured and ready to present paywalls.
  • Adds isFreeTrialAvailable to PaywallInfo.
  • Adds subscriptionStatusDidChange(to:) delegate function. If you're letting Superwall handle subscription logic you can use this to receive a callback whenever the user's internal subscription status changes. You can also listen to the published subscriptionStatus variable.
  • Adds a completion handler to Superwall.configure(...) that lets you know when Superwall has finished configuring. You can also listen to the published isConfigured variable.
  • If you let Superwall handle your subscription-related logic, we now assume that a non-consumable product on your paywall is a lifetime subscription. If not, you'll need to return a SubscriptionController from the delegate.
  • handleDeepLink(_:) now returns a discardable Bool indicating whether the deep link was handled. If you're using application(_:open:options:) you can return its value there.
  • Adds togglePaywallSpinner(isHidden:) to arbitrarily toggle the loading spinner on and off. This is particularly useful when you're doing async work when performing a custom action in handleCustomPaywallAction(withName:).
  • Adds a new event SubscriptionStatusDidChange which is logged on the dashboard whenever the user's subscription status changes.
  • You can now target device.isSandbox in rules.
  • Tweaks the loading indicator UI.
  • Prevents the registering of events that have the same name as internally tracked SuperwallEvents like paywall_open.
  • Adds a drawer display option which displays the paywall at 70% screen height on iOS 16 iPhones.
  • Adds $is_feature_gatable standard property to register calls.
  • Cleans up and reformats SDK logs.
  • If you're using SwiftUI, you can now call Superwall.configure in the init() of your App file. This means you don't need to have a UIApplicationDelegate.
  • You can access device.subscriptionStatus in a rule, which is a string that's either ACTIVE, INACTIVE, or UNKNOWN.
  • You no longer need to have swiftlint installed to run our example apps.
  • Adds static variable Superwall.isInitialized which is true when initialization is complete and Superwall.shared can be accessed.
  • Adds transaction_abandon, transaction_fail and `paywall...
Read more

3.0.0-rc.7

26 May 05:07
a87a6c4
Compare
Choose a tag to compare

Breaking Changes

  • Exposes the transactionBackgroundView PaywallOption to Objective-C by making it non-optional and adding a none case in place of setting it to nil.
  • Renames getPaywallViewController to getPaywall.
  • Renames paywallStatePublisher property on PaywallViewController to statePublisher.
  • Changes the presentation error domain code from SWPresentationError to SWKPresentationError.

Enhancements

  • Adds paywall caching. This is disabled by default but we'll roll this out to users accounts remotely. With this enhancement, your paywalls will load lightning fast and will reduce network load of your app.
  • Exposes Logging SuperwallOption to Objective C.
  • Exposes info on the PaywallViewController.
  • Adds rawTrialPeriodPrice, trialPeriodPrice, trialPeriodDailyPrice, trialPeriodWeeklyPrice, trialPeriodMonthlyPrice, trialPeriodYearlyPrice.

Fixes

  • Fixes issue where a crash would occur if storage was full and a persistent container couldn't be created.
  • Fixes thread safety issue when using a lazy variable to retrieve products.
  • If the internet is offline when trying to present a paywall, the paywall configuration hasn't been retrieved, and the user is not subscribed, it now throws a presentationError. If the internet reconnects future paywalls will show.
  • Fixes retry logic for requests.
  • Fixes crash when handling a deep link.
  • Creates a strong reference to the purchase controller as it was getting deallocated if you didn't keep a hold on it.

3.0.0-rc.6

13 May 14:02
Compare
Choose a tag to compare

Breaking Changes

  • Adds a PaywallViewControllerDelegate to the getPaywallViewController functions. This is mandatory and is how you control what happens after a paywall is dismissed.
  • The completion block of getPaywallViewController(forEvent:params:paywallOverrides:delegate:completion:) now accepts an optional PaywallViewController, an optional PaywallSkippedReason and an optional Error. This makes it easier to understand when the paywall was skipped vs when a real error occurred.
  • Renamed the PaywallResult case closed to declined.

Enhancements

  • Exposes PaywallOverrides and PaywallViewController to Objective-C.
  • Adds Objective-C convenience methods to PaywallOverrides.
  • Adds a device.isFirstAppOpen property that you can use in paywall rules. This is true for the very first time a user opens the app. When the user closes and reopens the app, this will be false.
  • Removes the need to tell us when you're going to present/have presented a PaywallViewController that has been retrieved using getPaywallViewController(...).
  • Adds isInspectable to the paywall web view if running on iOS 16.4+.
  • Exposes PaywallViewControllerDelegate to be used with getPaywallViewController(...)

Fixes

  • Fixes various memory related crashes.
  • Fixes a crash when calling reset() when a paywall is displayed.

3.0.0-rc.5

05 May 09:16
Compare
Choose a tag to compare

Fixes

  • Fixes bug where Superwall.shared.register's feature handler would not be called if the user is subscribed.

3.0.0-rc.4

04 May 17:25
a616836
Compare
Choose a tag to compare

Breaking Changes

  • Changes DismissState to PaywallResult.
  • Removes the closedForNextPaywall case from PaywallResult in favor of a new PaywallInfo property called closeReason, which can either be nil, .systemLogic, or .forNextPaywall.
  • Changes the PaywallPresentationHandler variables to functions.
  • Removes Superwall.shared.track. We're going all in on Superwall.shared.register baby!
  • Removes .error(Error) from PaywallSkippedReason in favor of a new PaywallState case .presentationError(Error).
  • Removes PaywallPresentationHandler completion block variables removed in favor of function calls with the same names.
  • Changes .onError of PaywallPresentationHandler to no longer be called when a paywall is intentionally not shown (i.e. user is subscribed, user is in holdout, no rule match, event not configured)
  • Adds .onSkip(reason:) to PaywallPresentationHandler to handle cases where paywall isn't shown because user is subscribed, user is in holdout, no rules match, event not configured

Enhancements

  • Adds getPaywallViewController! You can no request an actual view controller to present however you like. Check function documentation in Xcode for instructions – follow directions closely.
  • Changes default logging level to INFO.
  • Adds new automatically tracked paywall_decline event that can be used to present a new paywall when a user dismisses a paywall.
  • Allows transaction_abandon to trigger new paywalls when added to a campaign – called when a user abandons checkout (did you know 75% of the time, users abandon checkout when Apple's payment sheet comes up?!).
  • Adds .onSkip to PaywallPresentationHandler which is passed a PaywallSkippedReason when a paywall is not supposed to show.
  • Adds logging at INFO level, mansplaining exactly why a paywall is not shown when calling register or getPaywallViewController.
  • Adds new automatically tracked event presentation_request that gets sent with properties explaining why a paywall was or was not shown.

Fixes

  • Paywalls will now show even if you are missing products.

3.0.0-rc.3

28 Apr 18:16
c7ee601
Compare
Choose a tag to compare

Breaking Changes

  • Changes the logLevel to be non-optional and introduces a none case to turn off logging.
  • Removes all guides from the SDK documentation. From now on, our online docs provide guides and the SDK documentation is only there as a technical reference.
  • Changes TrackResultObjc to PresentationResultObjc
  • Removes convenience methods for creating PaywallPresentationHandlers because they were a bit confusing
  • Changes the return type of PurchaseController.restorePurchases() from bool to RestorationResult

Enhancements

  • If you're using SwiftUI, you can now call Superwall.configure in the init() of your App file. This means you don't need to have a UIApplicationDelegate.
  • Prevents validation of restorations and purchases if you're using a PurchaseController - it's now all on you!
  • Updates Objective-C sample app to use Superwall.register and removes legacy StoreKit code.
  • Simplifies SwiftUI and RevenueCat example app.
  • You can now access device.subscriptionStatus in a rule, which is a string that's either ACTIVE, INACTIVE, or UNKNOWN.
  • You no longer need to have swiftlint installed to run our example apps.
  • If you're not using a PurchaseController and a user comes across the "You're already subscribed to this product" popup, we will now correctly identify this as a restoration and not a purchase. This can happen when testing in sandbox if you purchase a product -> delete and reinstall the app -> open a paywall and purchase.
  • Adds static variable Superwall.isInitialized which is true when initialization is complete and Superwall.shared can be accessed.
  • Adds transaction_abandon and transaction_fail as potential triggers. This comes with a new DismissState case closedForNextPaywall, which is returned when dismissing one paywall for another.

Fixes

  • Fixes issue where an invalid URL provided for an "Open URL" click behavior would result in a crash.
  • Exposes PaywallPresentationHandler as SWKPaywallPresentationHandler for Objective-C.
  • Fixes issue #127, where calling identify with the same userId would prevent paywalls from showing.