Skip to content

[Swift] 4.0.0-alpha.3

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 31 Jul 16:52
Immutable release. Only release title and notes can be modified.
1a4a374

Breaking changes

Checkout errors are now a flat value type

CheckoutError changed from an enum with associated values to a struct with stable properties:

-func checkoutDidFail(error: CheckoutError) {
-    switch error {
-    case .checkoutExpired(_, let code):
-        recreateCart(for: code)
-    case .checkoutUnavailable(_, let reason):
-        handleUnavailableCheckout(reason)
-    case .sdkError(let underlyingError):
-        report(underlyingError)
-    }
-}
+func checkoutDidFail(error: CheckoutError) {
+    switch error.code {
+    case .cartExpired, .cartCompleted, .invalidCart:
+        recreateCart(for: error.code)
+    case .httpError, .networkError:
+        showRetry()
+    case .sdkError, .unknown:
+        report(error.underlyingError)
+    case .storefrontPasswordRequired, .customerAccountRequired:
+        handleStorefrontRequirement(error.code)
+    }
+}

The new properties are:

error.code
error.message
error.httpStatusCode
error.underlyingError

The intermediate CheckoutUnavailable type and enum cases such as .checkoutExpired, .checkoutUnavailable, and .sdkError have been removed.

Cancellation callbacks were renamed to dismissal

Buyer-initiated sheet closure is now described as dismissal:

 final class CheckoutCoordinator: CheckoutDelegate {
-    func checkoutDidCancel() {
+    func checkoutDidDismiss() {
         closeCheckout()
     }
 }

The SwiftUI modifier was also renamed:

 ShopifyCheckout(checkout: checkoutURL)
-    .onCancel {
+    .onDismiss {
         isCheckoutPresented = false
     }

Color scheme configuration was replaced by appearance

Configuration.colorScheme and the .colorScheme(...) view modifier were replaced by appearance:

 ShopifyCheckoutKit.configure {
-    $0.colorScheme = .web
+    $0.appearance = .storefront
 }
 ShopifyCheckout(checkout: checkoutURL)
-    .colorScheme(.automatic)
+    .appearance(.app(.automatic))

Migration mappings:

-.web
+.storefront

-.automatic
+.app(.automatic)

-.light
+.app(.light)

-.dark
+.app(.dark)

The default also changed from an automatic app color scheme to storefront appearance.

Log levels were normalized

LogLevel.all was removed and LogLevel.warn was added:

 ShopifyCheckoutKit.configure {
-    $0.logLevel = .all
+    $0.logLevel = .debug
 }

Log levels now behave as ordered thresholds:

debug → warn → error → none

The default changed from .error to .warn.

The Swift protocol module was renamed

Apps that directly depend on the protocol package must rename their product and import:

 .target(
     name: "YourApp",
     dependencies: [
         "ShopifyCheckoutKit",
-        "ShopifyCheckoutProtocol",
+        "EmbeddedCheckoutProtocol",
     ]
 )
-import ShopifyCheckoutProtocol
+import EmbeddedCheckoutProtocol

Protocol source types also moved into the EmbeddedCheckoutProtocol module.

Direct protocol event handlers receive envelopes

The underlying protocol descriptors now expose complete JSON-RPC notification and request envelopes. Direct EmbeddedCheckoutProtocol.Client integrations must update handler inputs accordingly.

-client.on(EmbeddedCheckoutProtocol.Event.complete) { checkout in
-    handleCompletion(checkout)
+client.on(EmbeddedCheckoutProtocol.Event.complete) { notification in
+    handleCompletion(notification.params.checkout)
 }

ShopifyCheckoutKit.CheckoutProtocol continues projecting common checkout events to their narrower payloads:

client.on(CheckoutProtocol.complete) { checkout in
    handleCompletion(checkout)
}

Window-open protocol types moved

WindowOpenRequest, WindowOpenResult, and the window-open descriptor moved from ShopifyCheckoutKit into EmbeddedCheckoutProtocol.

Prefer the Checkout Kit facade when connecting through Checkout Kit:

-client.on(CheckoutProtocol.windowOpen) { request in
-    return .success
+client.on(CheckoutProtocol.windowOpen) { request in
+    open(URL(string: request.url)!)
+    return EmbeddedCheckoutProtocol.WindowOpenResult(
+        ucp: /* response envelope */,
+        continueURL: nil,
+        messages: nil
+    )
 }

Additive changes

Observable preload state

preload(checkout:) now returns an optional CheckoutPreload handle:

-ShopifyCheckoutKit.preload(checkout: checkoutURL)
+let preload = ShopifyCheckoutKit.preload(checkout: checkoutURL)
+preload?.onStateChange = { state in
+    switch state {
+    case .ready:
+        showCheckoutReady()
+    case .failed(let reason):
+        recordPreloadFailure(reason)
+    default:
+        break
+    }
+}

The handle publishes its latest state through:

@Published public private(set) var state: PreloadState

Retain the handle for as long as preload changes need to be observed.

New checkout error codes

The flattened error model adds stable codes for:

.customerAccountRequired
.httpError
.networkError
.sdkError

HTTP failures expose their response status through httpStatusCode.

Warning-level logging

OSLogger now provides:

logger.warn("Checkout will retry")

Selecting .warn emits warnings and errors while suppressing debug output.

Behavior changes

Transient navigation failures are retried once

Checkout now retries the initial checkout navigation once for selected transient network failures, including connection loss, host lookup failures, timeouts, and temporary resource unavailability.

If the retry also fails, the SDK reports a terminal .networkError.

Preload failures are observable

Preload can now transition to:

.failed(reason: .httpError(statusCode: status))
.failed(reason: .navigationFailed)
.failed(reason: .keepAliveLost)
.failed(reason: .protocolError)

These states describe preload availability and do not necessarily mean a later checkout presentation will fail.

Protocol decode failures are logged

Malformed or unsupported protocol messages now provide more consistent diagnostic logging across the native and web implementations.

What's Changed

  • Flatten Swift checkout failure type by @kiftio in #537
  • [Android][Swift] Rename oncancel to ondismiss in swift and android by @kiftio in #482
  • Retry on didFailProvisionalNavigation by @markmur in #492
  • [Swift] Add preload state observability by @markmur in #445
  • [Swift] remove color scheme from automatic swift by @kiftio in #470
  • [Swift] Canonicalize LogLevel to debug/warn/error/none by @markmur in #441
  • Add decode logging parity for Web + Swift + Android by @markmur in #437
  • Widen protocol events to expose full envelope by @markmur in #398
  • Add Swift checkout appearance configuration by @tiagocandido in #421
  • Derive Swift checkout branding from color scheme by @tiagocandido in #405
  • Move windowOpen to protocol by @markmur in #386
  • Add native checkout close selector for RN E2E by @kyle-schellen in #333
  • Rename ShopifyCheckoutProtocol to EmbeddedCheckoutProtocol by @markmur in #354
  • Make the OpenRPC spec the single source of truth for the Swift protocol layer by @markmur in #330
  • Bump protocol to 2026.04.08.1-alpha.2, Swift and Android to 4.0.0-alpha.3 by @kiftio in #563

Full Changelog: 4.0.0-alpha.2...4.0.0-alpha.3