Releases: superwall/Superwall-iOS
3.0.0-beta.4
Breaking Changes
- Moves back to using
Superwall.shared.identify(userId: userId)
andreset()
instead of logIn/createAccount/logout/reset. This is so that it's easier for integration. However, you can now pass anIdentityOptions
object toidentify(userId:options)
. This should only be used in advanced use cases. By setting therestorePaywallAssignments
property ofIdentityOptions
totrue
, 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.
Enhancements
- Adds
hasActiveSubscriptionDidChange(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 publishedhasActiveSubscription
variable. - Adds a completion handler to
Superwall.configure(...)
that lets you know when Superwall has finished configuring. You can also listen to the publishedisConfigured
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 discardableBool
indicating whether the deep link was handled. If you're usingapplication(_: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 inhandleCustomPaywallAction(withName:)
.
Fixes
- Fixes occasional thread safety related crash when loading products.
- Reverts an issue from the last beta where the paywall spinner would move up before the payment sheet appeared.
3.0.0-beta.3
Fixes
- Fixes potential crash due to a using a lazy variable.
3.0.0-beta.2
Breaking Changes
- Moves all functions and variables to the
shared
instance for consistency, e.g. it's nowSuperwall.shared.track()
instead ofSuperwall.track()
.
Enhancements
- Readds
Superwall.shared.logLevel
as a top level static convenience variable so you can easily change the log level. - Adds
isLoggedIn
to user properties, which means you can create a rule based on whether the user is logged in vs. whether they're anonymous.
Fixes
- Fixes bug in
<iOS 14
where the spinner wasn't appearing when transacting. - Fixes bug where PaywallOverrides weren't being passed in to the paywall.
- Fixes bug where purchasing, deleting then reinstalling your app, and tapping a purchase button would throw an error.
- Fixes an rare crash associated with the loading and saving of Core Data.
3.0.0-beta.1
This is the first beta for SuperwallKit
, the framework formally known as Paywall
!
When out of beta, this will be a major release, containing lots of breaking changes, enhancements and some bug fixes.
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 out sample apps to v3, including RevenueCat+SuperwallKit and Objective-C apps. For new users, we've created a Quick Start Guide to get up and running in no time. Finally, we recommend you check out our updated docs.
Breaking Changes
- Renames the package from
Paywall
toSuperwallKit
. - Renames the primary static class for integrating Superwall from
Paywall
toSuperwall
. - Sets the minimum iOS version to iOS 13.
- Renames
preloadPaywalls(forTriggers:)
topreloadPaywalls(forEvents:)
- Renames
configure(apiKey:userId:delegate:options:)
toconfigure(apiKey:delegate:options:)
. This means you no longer provide auserId
with configure. Instead you must use the new identity API detailed below. - Changes
PaywallOptions
toSuperwallOptions
. This now clearly defines which of the options are explicit to paywalls vs other configuration options within the SDK. - Renames
Superwall.trigger(event:)
toSuperwall.track(event:)
. We found that having separate implicit (Superwall.track(event:)
) and explicit (Superwall.trigger(event:)
) trigger functions caused confusion. So from now on, you'll just useSuperwall.track(event:)
for all events within your app. - Renames
Paywall.EventName
toSuperwallEvent
and removes.manualPresent
as aSuperwallEvent
. - Renames
PaywallDelegate
toSuperwallDelegate
. - Superwall automatically handles all subscription-related logic, meaning that it's no longer a requirement to implement any of the delegate methods. Note that if you're using RevenueCat, you will still need to use the delegate methods. This is because the Superwall-handled subscription status is App Store account-specific, whereas RevenueCat is logged in user-specific. If this isn't a problem, you can just set RevenueCat in observer mode and we'll take care of the rest :)
- Moves purchasing logic from the delegate into a protocol called
SubscriptionController
. You return yourSubscriptionController
from the delegate methodsubscriptionController()
. - For Swift users, this changes the
SubscriptionController
methodpurchase(product:)
to an async function that returns aPurchaseResult
. Here, you need to return the result of the user attempting to purchase a product, making sure you handle all cases ofPurchaseResult
:.purchased
,.cancelled
,.pending
,failed(Error)
. - For Objective-C users, this changes the delegate method
purchase(product:)
topurchase(product:completion:)
. You call the completion block with the result of the user attempting to purchase a product, making sure you handle all cases ofPurchaseResultObjc
:.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
identify(userId:)
in favor of the new Identity API detailed below. - 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 functionSuperwall.track()
. Take a look at our SwiftUI example app to see how that works. - Changes the
period
andperiodly
attributes for 2, 3 and 6 month products. Previously, theperiod
would be "month", and theperiodly
would be "monthly" for all three. Now theperiod
returns "2 months", "quarter", "6 months" and theperiodly
returns "every 2 months", "quarterly", and "every 6 months".
Enhancements
- New identity API:
logIn(userId:)
: Logs in a user with theiruserId
to retrieve paywalls that they've been assigned to.createAccount(userId:)
: Creates an account with Superwall. This links auserId
to Superwall's automatically generated alias.logOut(userId:)
: Logs out the user, which resets on-device paywall assignments and theuserId
stored by Superwall.reset()
: Resets theuserId
, on-device paywall assignments, and data stored by Superwall. This can be called even if the user isn't logged in.
- The identity API can be accessed using async/await or completion handlers.
- New function
Superwall.publisher(forEvent:params:overrides)
which returns aPaywallStatePublisher
(AnyPublisher<PaywallState, Never>
) for those Combine lovers. By subscribing to this publisher, you can receive state updates of your paywall. We've updated our sample apps to show you how to use that. - Adds
Superwall.isLoggedIn
to check whether the user is logged in to the SDK or not. This will be true if you've previously calledlogIn(userId:)
orcreateAccount(userId:)
. - 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 innil
for a specific attribute insetUserAttributes(_:)
. - Adds
getTrackResult(forEvent:params:)
. This returns aTrackResult
which tells you the result of tracking an event, without actually tracking it. This is useful if you want to figure out whether a paywall will show in the future. - Logs when products fail to load with a link to help diagnose the cause.
- Adds a published property
hasActiveSubscription
, which you can check to determine whether Superwall detects an active subscription. Its value is stored on disk and synced with the active purchases on device. If you're using Combine or SwiftUI, you can subscribe or bind to this to get notified whenever the user's subscription status changes. If you're implementing your ownSubscriptionController
, you should rely on your own logic to determine subscription status. - 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
toPaywallInfo
. - Tracks whenever the paywall isn't presented for easier debugging.
Fixes
- Fixes a caching issue where the paywall was still showing in free trial mode when it shouldn't have. This was happening if you had purchased a free trial, let it expire, then reopened the paywall. Note that in Sandbox environments this issue may still occur due to introductory offers not being added to a receipt until after a purchase.
- The API uses background threads wherever possible, dispatching to the main thread only when necessary and when returning from completion blocks.
- The API is now fully compatible with Objective-C.
- Setting the
PaywallOption
automaticallyDismiss
tofalse
now keeps the loading indicator visible after restoring and successfully purchasing until you manually dismiss the paywall. - Improves the speed of requests by changing the cache policy of requests to our servers.
- Fixes
session_start
,app_launch
andfirst_seen
not being tracked if the SDK was initialised a few seconds after app launch. - Stops the unnecessary retemplating of paywall variables when coming back to the paywall after visiting a link via the in-app browser.
- Removes the transaction timeout popup. This was causing a raft of issues so we now rely on overlayTimeout to cancel the transaction flow.
2.5.8
Enhancements
- Adds
isExternalDataCollectionEnabled
data privacyPaywallOption
. Whenfalse
, prevents non-Superwall events and properties from being sent back to the superwall servers. - Adds an
X-Is-Sandbox
header to all requests such that sandbox data doesn't affect your production analytics on superwall.com.
Fixes
- Fixes a bug that prevented the correct calculation of a new app session.
- Fixes missing loading times of the webview and products.
2.5.6
2.5.5
2.5.4
2.5.3
2.5.2
You know when app devs are lazy and just put "bug fixes and performance improvements" in their release notes? Well this release contains bug fixes and performance improvements... for real though!
Fixes
- Fixed memory and performance issues associated with the shimmer view when loading a paywall. Special thanks to Mattias from Planta for spotting that one and Jakub from Hornet for helping us solve performance issues. We've rebuilt the shimmer view and only add it when the paywall is visible and loading. This means it doesn't get added to paywalls preloading in the background. After loading, we remove the shimmer view from memory.
- Moves internal operations for templating paywall variables from the main thread to a background thread. This prevents hangs on the main thread.
- Stops
UIAlertViewControllers
being unnecessarily created when loading a paywall. - Removes the dependency on
TPInAppReceipt
from our podspec and replaces it with aASN1Swift
dependency to keep it in line with our Swift Package file. Thanks to Semyon from Appex for spotting that!