From 16b7e6f6f996d8261c10a755813ec982f1ed4b6d Mon Sep 17 00:00:00 2001 From: Brian Anglin Date: Mon, 29 Jun 2026 16:07:00 -0700 Subject: [PATCH 1/6] Clarify OneSignal user ID attribute --- CHANGELOG.md | 1 + .../Analytics/Attribution/IntegrationAttribute.swift | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1187f2e8df..d5b6468703 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The changelog for `SuperwallKit`. Also see the [releases](https://github.com/sup - Adds support for annual subscriptions that are billed monthly. - Added `EventTrackingBehavior` enum and `SuperwallOptions.eventTrackingBehavior` property for GDPR-compliant event collection control. Use `.all` (default) to track everything, `.superwallOnly` to suppress user-initiated tracking, trigger fires, and user-attribute updates while keeping internal SDK events, or `.none` to stop all event collection entirely. The behavior can also be changed at runtime via `Superwall.shared.eventTrackingBehavior`. - Deprecated `SuperwallOptions.isExternalDataCollectionEnabled`. Setting it to `false` now maps to `.superwallOnly`; setting it back to `true` maps to `.all`. +- Clarifies that `IntegrationAttribute.onesignalId` should be set to the OneSignal User ID used by the OneSignal integration. ### Fixes diff --git a/Sources/SuperwallKit/Analytics/Attribution/IntegrationAttribute.swift b/Sources/SuperwallKit/Analytics/Attribution/IntegrationAttribute.swift index 29603c987c..d0a713f32a 100644 --- a/Sources/SuperwallKit/Analytics/Attribution/IntegrationAttribute.swift +++ b/Sources/SuperwallKit/Analytics/Attribution/IntegrationAttribute.swift @@ -26,7 +26,7 @@ public enum IntegrationAttribute: Int { /// The Braze `alias_label` in User Alias Object. case brazeAliasLabel - /// The OneSignal Player identifier for the user. + /// The OneSignal User ID (`onesignal_id`) for the user. case onesignalId /// The Facebook Anonymous identifier for the user. From 688cb7ac6d72d180d21d97221fa5ab843312ccb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yusuf=20To=CC=88r?= <3296904+yusuftor@users.noreply.github.com> Date: Tue, 30 Jun 2026 22:06:51 +0200 Subject: [PATCH 2/6] Gate billing-plan APIs at iOS 26.5, not 26.4 Product.SubscriptionInfo.PricingTerms (and the related BillingPlanType / billing-plan purchase option) ship in the iOS 26.5 SDK, not 26.4. The runtime availability checks gated them at 26.4, which compiles against an SDK that annotates the symbols at 26.4 but errors against the 26.5 SDK ("only available in iOS 26.5 or newer"). Bump the @available and #available floors to 26.5 (gating higher than the floor is always safe) and update the doc comments to match. Co-Authored-By: Claude Opus 4.8 (1M context) --- Sources/SuperwallKit/Models/Product/AppStoreProduct.swift | 2 +- .../StoreKit/Products/StoreProduct/SK2StoreProduct.swift | 6 +++--- .../StoreKit/Products/StoreProduct/StoreProduct.swift | 2 +- .../Purchasing/StoreKit 2/ProductPurchaserSK2.swift | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Sources/SuperwallKit/Models/Product/AppStoreProduct.swift b/Sources/SuperwallKit/Models/Product/AppStoreProduct.swift index e1ccd51a64..8de7232fef 100644 --- a/Sources/SuperwallKit/Models/Product/AppStoreProduct.swift +++ b/Sources/SuperwallKit/Models/Product/AppStoreProduct.swift @@ -17,7 +17,7 @@ public final class AppStoreProduct: NSObject, Codable, Sendable { /// Two Superwall Products that share the same Apple `productIdentifier` but /// configure different billing plans (e.g. annual up-front and /// monthly-commitment annual) are merchandised as distinct entries on a - /// paywall. Available on iOS 26.4+ subscription products with multiple + /// paywall. Available on iOS 26.5+ subscription products with multiple /// billing plans configured in App Store Connect. @objc(SWKBillingPlanType) public enum BillingPlanType: Int, Sendable { diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift index 2480c66d8b..2f3d611481 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift @@ -44,7 +44,7 @@ struct SK2StoreProduct: StoreProductType { self.billingPlanType = billingPlanType #if compiler(>=6.3) - if #available(iOS 26.4, macOS 26.4, tvOS 26.4, watchOS 26.4, visionOS 26.4, *), + if #available(iOS 26.5, macOS 26.5, tvOS 26.5, watchOS 26.5, visionOS 26.5, *), let term = Self.findPricingTerm(for: billingPlanType, in: sk2Product) { // Use the commitment *period* (= year for an annual MONTHLY product) // so the paywall reads as the underlying product (not its billing @@ -63,7 +63,7 @@ struct SK2StoreProduct: StoreProductType { ) self.cachedSelectedPrice = term.billingPrice * Decimal(cycles) self.cachedSelectedSubscriptionPeriod = term.commitmentInfo.period - // Intro offers are per-billing-plan on iOS 26.4+: each `PricingTerms` + // Intro offers are per-billing-plan on iOS 26.5+: each `PricingTerms` // has its own `subscriptionOffers` array. Pull the plan-specific // introductory offer (if any) so the paywall surfaces the trial / // intro pricing configured against this billing plan rather than @@ -241,7 +241,7 @@ struct SK2StoreProduct: StoreProductType { } #if compiler(>=6.3) - @available(iOS 26.4, macOS 26.4, tvOS 26.4, watchOS 26.4, visionOS 26.4, *) + @available(iOS 26.5, macOS 26.5, tvOS 26.5, watchOS 26.5, visionOS 26.5, *) private static func findPricingTerm( for billingPlanType: AppStoreProduct.BillingPlanType?, in sk2Product: SK2Product diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StoreProduct.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StoreProduct.swift index 2cb565fb4a..027eff8675 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StoreProduct.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StoreProduct.swift @@ -73,7 +73,7 @@ public final class StoreProduct: NSObject, StoreProductType, Sendable { /// Whether there's an Apple billing plan to use for this product on /// the current runtime — i.e. a non-null `billingPlanType` is /// configured on the Superwall Product AND the matching pricing term - /// is exposed in `Product.SubscriptionInfo.pricingTerms` (iOS 26.4+ + /// is exposed in `Product.SubscriptionInfo.pricingTerms` (iOS 26.5+ /// in a supported region). /// /// Returns `false` for legacy products with no billing plan diff --git a/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/StoreKit 2/ProductPurchaserSK2.swift b/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/StoreKit 2/ProductPurchaserSK2.swift index dd6174cc90..a85c440d3a 100644 --- a/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/StoreKit 2/ProductPurchaserSK2.swift +++ b/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/StoreKit 2/ProductPurchaserSK2.swift @@ -102,10 +102,10 @@ final class ProductPurchaserSK2: Purchasing { #endif #if compiler(>=6.3) - // Apply the configured Apple billing plan (iOS 26+). If the runtime is + // Apply the configured Apple billing plan (iOS 26.5+). If the runtime is // older or no plan is configured, the purchase proceeds with Apple's // default plan. - if #available(iOS 26.4, macOS 26.4, tvOS 26.4, watchOS 26.4, visionOS 26.4, *), + if #available(iOS 26.5, macOS 26.5, tvOS 26.5, watchOS 26.5, visionOS 26.5, *), let plan = product.billingPlanType { let sk2Plan: StoreKit.Product.SubscriptionInfo.BillingPlanType switch plan { From 47ca176f32147e90355bac3d97b49e644261365f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yusuf=20To=CC=88r?= <3296904+yusuftor@users.noreply.github.com> Date: Tue, 30 Jun 2026 22:11:42 +0200 Subject: [PATCH 3/6] Revert "Gate billing-plan APIs at iOS 26.5, not 26.4" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 688cb7ac6. Apple's SDK header declares `Product.SubscriptionInfo.pricingTerms` (and thus the `PricingTerms` type it returns) as `@available(iOS 26.4, ...)`, not 26.5 — the earlier "26.5-only" claim was incorrect. The original 26.4 gate was right; gating at 26.5 would have wrongly denied billing plans to 26.4 devices. Co-Authored-By: Claude Opus 4.8 (1M context) --- Sources/SuperwallKit/Models/Product/AppStoreProduct.swift | 2 +- .../StoreKit/Products/StoreProduct/SK2StoreProduct.swift | 6 +++--- .../StoreKit/Products/StoreProduct/StoreProduct.swift | 2 +- .../Purchasing/StoreKit 2/ProductPurchaserSK2.swift | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Sources/SuperwallKit/Models/Product/AppStoreProduct.swift b/Sources/SuperwallKit/Models/Product/AppStoreProduct.swift index 8de7232fef..e1ccd51a64 100644 --- a/Sources/SuperwallKit/Models/Product/AppStoreProduct.swift +++ b/Sources/SuperwallKit/Models/Product/AppStoreProduct.swift @@ -17,7 +17,7 @@ public final class AppStoreProduct: NSObject, Codable, Sendable { /// Two Superwall Products that share the same Apple `productIdentifier` but /// configure different billing plans (e.g. annual up-front and /// monthly-commitment annual) are merchandised as distinct entries on a - /// paywall. Available on iOS 26.5+ subscription products with multiple + /// paywall. Available on iOS 26.4+ subscription products with multiple /// billing plans configured in App Store Connect. @objc(SWKBillingPlanType) public enum BillingPlanType: Int, Sendable { diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift index 2f3d611481..2480c66d8b 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift @@ -44,7 +44,7 @@ struct SK2StoreProduct: StoreProductType { self.billingPlanType = billingPlanType #if compiler(>=6.3) - if #available(iOS 26.5, macOS 26.5, tvOS 26.5, watchOS 26.5, visionOS 26.5, *), + if #available(iOS 26.4, macOS 26.4, tvOS 26.4, watchOS 26.4, visionOS 26.4, *), let term = Self.findPricingTerm(for: billingPlanType, in: sk2Product) { // Use the commitment *period* (= year for an annual MONTHLY product) // so the paywall reads as the underlying product (not its billing @@ -63,7 +63,7 @@ struct SK2StoreProduct: StoreProductType { ) self.cachedSelectedPrice = term.billingPrice * Decimal(cycles) self.cachedSelectedSubscriptionPeriod = term.commitmentInfo.period - // Intro offers are per-billing-plan on iOS 26.5+: each `PricingTerms` + // Intro offers are per-billing-plan on iOS 26.4+: each `PricingTerms` // has its own `subscriptionOffers` array. Pull the plan-specific // introductory offer (if any) so the paywall surfaces the trial / // intro pricing configured against this billing plan rather than @@ -241,7 +241,7 @@ struct SK2StoreProduct: StoreProductType { } #if compiler(>=6.3) - @available(iOS 26.5, macOS 26.5, tvOS 26.5, watchOS 26.5, visionOS 26.5, *) + @available(iOS 26.4, macOS 26.4, tvOS 26.4, watchOS 26.4, visionOS 26.4, *) private static func findPricingTerm( for billingPlanType: AppStoreProduct.BillingPlanType?, in sk2Product: SK2Product diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StoreProduct.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StoreProduct.swift index 027eff8675..2cb565fb4a 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StoreProduct.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/StoreProduct.swift @@ -73,7 +73,7 @@ public final class StoreProduct: NSObject, StoreProductType, Sendable { /// Whether there's an Apple billing plan to use for this product on /// the current runtime — i.e. a non-null `billingPlanType` is /// configured on the Superwall Product AND the matching pricing term - /// is exposed in `Product.SubscriptionInfo.pricingTerms` (iOS 26.5+ + /// is exposed in `Product.SubscriptionInfo.pricingTerms` (iOS 26.4+ /// in a supported region). /// /// Returns `false` for legacy products with no billing plan diff --git a/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/StoreKit 2/ProductPurchaserSK2.swift b/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/StoreKit 2/ProductPurchaserSK2.swift index a85c440d3a..dd6174cc90 100644 --- a/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/StoreKit 2/ProductPurchaserSK2.swift +++ b/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/StoreKit 2/ProductPurchaserSK2.swift @@ -102,10 +102,10 @@ final class ProductPurchaserSK2: Purchasing { #endif #if compiler(>=6.3) - // Apply the configured Apple billing plan (iOS 26.5+). If the runtime is + // Apply the configured Apple billing plan (iOS 26+). If the runtime is // older or no plan is configured, the purchase proceeds with Apple's // default plan. - if #available(iOS 26.5, macOS 26.5, tvOS 26.5, watchOS 26.5, visionOS 26.5, *), + if #available(iOS 26.4, macOS 26.4, tvOS 26.4, watchOS 26.4, visionOS 26.4, *), let plan = product.billingPlanType { let sk2Plan: StoreKit.Product.SubscriptionInfo.BillingPlanType switch plan { From 140015108c2aa33bbd6704ddc1741f096bb97375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yusuf=20To=CC=88r?= <3296904+yusuftor@users.noreply.github.com> Date: Tue, 30 Jun 2026 22:27:48 +0200 Subject: [PATCH 4/6] Gate billing-plan SDK symbols on compiler 6.3.2, not 6.3 PricingTerms / BillingPlanType / the billing-plan purchase option ship in the Xcode 26.5 SDK (Swift 6.3.2). Xcode 26.4 (Swift 6.3) backdates their runtime availability to iOS 26.4 but doesn't include the symbols, so the `#if compiler(>=6.3)` gate let the code compile against the 26.4 SDK and failed with "'PricingTerms' is not a member type of 'Product.Subscription Info'". Tighten all three billing-plan gates to compiler(>=6.3.2) so the blocks are excluded on 26.4 toolchains and compiled on 26.5+. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../StoreKit/Products/StoreProduct/SK2StoreProduct.swift | 4 ++-- .../Purchasing/StoreKit 2/ProductPurchaserSK2.swift | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift index 2480c66d8b..058c97f0f5 100644 --- a/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift +++ b/Sources/SuperwallKit/StoreKit/Products/StoreProduct/SK2StoreProduct.swift @@ -43,7 +43,7 @@ struct SK2StoreProduct: StoreProductType { self.entitlements = entitlements self.billingPlanType = billingPlanType - #if compiler(>=6.3) + #if compiler(>=6.3.2) if #available(iOS 26.4, macOS 26.4, tvOS 26.4, watchOS 26.4, visionOS 26.4, *), let term = Self.findPricingTerm(for: billingPlanType, in: sk2Product) { // Use the commitment *period* (= year for an annual MONTHLY product) @@ -240,7 +240,7 @@ struct SK2StoreProduct: StoreProductType { return underlyingSK2Product.subscription?.introductoryOffer } - #if compiler(>=6.3) + #if compiler(>=6.3.2) @available(iOS 26.4, macOS 26.4, tvOS 26.4, watchOS 26.4, visionOS 26.4, *) private static func findPricingTerm( for billingPlanType: AppStoreProduct.BillingPlanType?, diff --git a/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/StoreKit 2/ProductPurchaserSK2.swift b/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/StoreKit 2/ProductPurchaserSK2.swift index dd6174cc90..7b584ec896 100644 --- a/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/StoreKit 2/ProductPurchaserSK2.swift +++ b/Sources/SuperwallKit/StoreKit/Transactions/Purchasing/StoreKit 2/ProductPurchaserSK2.swift @@ -101,10 +101,7 @@ final class ProductPurchaserSK2: Purchasing { } #endif - #if compiler(>=6.3) - // Apply the configured Apple billing plan (iOS 26+). If the runtime is - // older or no plan is configured, the purchase proceeds with Apple's - // default plan. + #if compiler(>=6.3.2) if #available(iOS 26.4, macOS 26.4, tvOS 26.4, watchOS 26.4, visionOS 26.4, *), let plan = product.billingPlanType { let sk2Plan: StoreKit.Product.SubscriptionInfo.BillingPlanType From edb7ea401250f90a7d8c0d4492feccee79099b57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yusuf=20To=CC=88r?= <3296904+yusuftor@users.noreply.github.com> Date: Tue, 30 Jun 2026 22:41:55 +0200 Subject: [PATCH 5/6] Update version --- CHANGELOG.md | 6 ++++++ Sources/SuperwallKit/Misc/Constants.swift | 2 +- .../SuperwallKit/Network/Device Helper/SwiftVersion.swift | 8 +++++++- SuperwallKit.podspec | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1187f2e8df..dbd031255d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ The changelog for `SuperwallKit`. Also see the [releases](https://github.com/superwall/Superwall-iOS/releases) on GitHub. +## 4.16.1 + +### Fixes + +- Makes sure that the compiler directive is correct for billing plan types so that the SDK builds in Xcode version 26.4. + ## 4.16.0 ### Enhancements diff --git a/Sources/SuperwallKit/Misc/Constants.swift b/Sources/SuperwallKit/Misc/Constants.swift index 5338fe7359..e38ade56b0 100644 --- a/Sources/SuperwallKit/Misc/Constants.swift +++ b/Sources/SuperwallKit/Misc/Constants.swift @@ -18,5 +18,5 @@ let sdkVersion = """ */ let sdkVersion = """ -4.16.0 +4.16.1 """ diff --git a/Sources/SuperwallKit/Network/Device Helper/SwiftVersion.swift b/Sources/SuperwallKit/Network/Device Helper/SwiftVersion.swift index b8b16685d7..89a92fb2cc 100644 --- a/Sources/SuperwallKit/Network/Device Helper/SwiftVersion.swift +++ b/Sources/SuperwallKit/Network/Device Helper/SwiftVersion.swift @@ -110,7 +110,13 @@ extension DeviceHelper { } func currentCompilerVersion() -> String { - #if compiler(>=6.3) + #if compiler(>=6.4) + return "6.4" + #elseif compiler(>=6.3.3) + return "6.3.3" + #elseif compiler(>=6.3.2) + return "6.3.2" + #elseif compiler(>=6.3) return "6.3" #elseif compiler(>=6.2.4) return "6.2.4" diff --git a/SuperwallKit.podspec b/SuperwallKit.podspec index 27d2d5647d..3115a9e217 100644 --- a/SuperwallKit.podspec +++ b/SuperwallKit.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "SuperwallKit" - s.version = "4.16.0" + s.version = "4.16.1" s.summary = "Superwall: In-App Paywalls Made Easy" s.description = "Paywall infrastructure for mobile apps :) we make things like editing your paywall and running price tests as easy as clicking a few buttons. superwall.com" From b8e9df116bcc2817492ccec2df838f4b3787aec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yusuf=20To=CC=88r?= <3296904+yusuftor@users.noreply.github.com> Date: Wed, 1 Jul 2026 11:00:26 +0200 Subject: [PATCH 6/6] Update CHANGELOG.md --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f0b84f07c..9acd565130 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ The changelog for `SuperwallKit`. Also see the [releases](https://github.com/sup ## 4.16.1 +### Enhancements + +- Clarifies that `IntegrationAttribute.onesignalId` should be set to the OneSignal User ID used by the OneSignal integration. + ### Fixes - Makes sure that the compiler directive is correct for billing plan types so that the SDK builds in Xcode version 26.4. @@ -16,7 +20,6 @@ The changelog for `SuperwallKit`. Also see the [releases](https://github.com/sup - Adds support for annual subscriptions that are billed monthly. - Added `EventTrackingBehavior` enum and `SuperwallOptions.eventTrackingBehavior` property for GDPR-compliant event collection control. Use `.all` (default) to track everything, `.superwallOnly` to suppress user-initiated tracking, trigger fires, and user-attribute updates while keeping internal SDK events, or `.none` to stop all event collection entirely. The behavior can also be changed at runtime via `Superwall.shared.eventTrackingBehavior`. - Deprecated `SuperwallOptions.isExternalDataCollectionEnabled`. Setting it to `false` now maps to `.superwallOnly`; setting it back to `true` maps to `.all`. -- Clarifies that `IntegrationAttribute.onesignalId` should be set to the OneSignal User ID used by the OneSignal integration. ### Fixes