diff --git a/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayAuthorizationDelegate/ApplePayAuthorizationDelegate+Controller.swift b/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayAuthorizationDelegate/ApplePayAuthorizationDelegate+Controller.swift index e1660611..598bd3b9 100644 --- a/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayAuthorizationDelegate/ApplePayAuthorizationDelegate+Controller.swift +++ b/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayAuthorizationDelegate/ApplePayAuthorizationDelegate+Controller.swift @@ -224,7 +224,7 @@ extension ApplePayAuthorizationDelegate: PKPaymentAuthorizationControllerDelegat // Taxes may become pending again fail to resolve despite updating within the didUpdatePaymentMethod // So we retry one time to see if the error clears on retry - _ = try await Task.retrying(priority: nil, maxRetryCount: 1) { + _ = try await Task.retrying(priority: nil, maxRetryCount: 1) { @MainActor in try await self.controller.storefront.cartPaymentUpdate( id: cartID, totalAmount: totalAmount, @@ -250,7 +250,9 @@ extension ApplePayAuthorizationDelegate: PKPaymentAuthorizationControllerDelegat ShopifyAcceleratedCheckouts.logger.debug("paymentAuthorizationControllerDidFinish, state: \(state)") controller.dismiss { - Task { try? await self.transition(to: .completed) } + Task { @MainActor in + try? await self.transition(to: .completed) + } } } diff --git a/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayAuthorizationDelegate/ApplePayAuthorizationDelegate.swift b/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayAuthorizationDelegate/ApplePayAuthorizationDelegate.swift index 1a869251..0d6c9334 100644 --- a/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayAuthorizationDelegate/ApplePayAuthorizationDelegate.swift +++ b/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayAuthorizationDelegate/ApplePayAuthorizationDelegate.swift @@ -41,6 +41,7 @@ extension PKPaymentAuthorizationController: PaymentAuthorizationController {} typealias PKAuthorizationControllerFactory = (PKPaymentRequest) -> PaymentAuthorizationController @available(iOS 16.0, *) +@MainActor class ApplePayAuthorizationDelegate: NSObject, ObservableObject { let configuration: ApplePayConfigurationWrapper let abortError = ShopifyAcceleratedCheckouts.Error.invariant(expected: "cart") @@ -173,7 +174,7 @@ class ApplePayAuthorizationDelegate: NSObject, ObservableObject { break default: let cartID = try pkEncoder.cartID.get() - try? await _Concurrency.Task.retrying(clock: clock) { + try? await _Concurrency.Task.retrying(clock: clock) { @MainActor in try await self.controller.storefront.cartRemovePersonalData(id: cartID) }.value diff --git a/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayButton.swift b/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayButton.swift index bb60e6a6..49fd3623 100644 --- a/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayButton.swift +++ b/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayButton.swift @@ -109,6 +109,7 @@ struct ApplePayButton: View { /// This is an internal view to allow Environment injection of the shared configuration app wide @available(iOS 16.0, *) @available(macOS, unavailable) +@MainActor struct Internal_ApplePayButton: View { private let label: PayWithApplePayButtonLabel private let style: PayWithApplePayButtonStyle @@ -143,7 +144,7 @@ struct Internal_ApplePayButton: View { buttonType: label.pkPaymentButtonType, buttonStyle: style.pkPaymentButtonStyle, cornerRadius: cornerRadius ?? 8, - action: { Task { await controller.onPress() } } + action: { Task { @MainActor in await controller.onPress() } } ) .id("\(colorScheme)-\(style.pkPaymentButtonStyle.rawValue)") .frame(height: 48) diff --git a/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayViewController.swift b/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayViewController.swift index e397fd4d..a0c076b6 100644 --- a/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayViewController.swift +++ b/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ApplePay/ApplePayViewController.swift @@ -26,6 +26,7 @@ import ShopifyCheckoutKit import SwiftUI @available(iOS 16.0, *) +@MainActor protocol PayController: AnyObject { var cart: StorefrontAPI.Types.Cart? { get set } var storefront: StorefrontAPIProtocol { get set } @@ -35,6 +36,7 @@ protocol PayController: AnyObject { } @available(iOS 16.0, *) +@MainActor class ApplePayViewController: WalletController, PayController { @Published var paymentController: PKPaymentAuthorizationController? @@ -96,7 +98,7 @@ class ApplePayViewController: WalletController, PayController { self.client = LifecycleObservingClient(base: client, onComplete: { [weak self] in guard let self else { return } - Task { + Task { @MainActor in try? await self.authorizationDelegate.transition(to: .completed) } }) @@ -113,9 +115,7 @@ class ApplePayViewController: WalletController, PayController { ShopifyAcceleratedCheckouts.logger.error( "[startPayment] Failed to setup cart: \(error)" ) - Task { @MainActor in - self.onCheckoutFail?(.sdkError(underlying: error, recoverable: false)) - } + self.onCheckoutFail?(.sdkError(underlying: error, recoverable: false)) } do { diff --git a/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ShopPay/ShopPayButton.swift b/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ShopPay/ShopPayButton.swift index 7c4096ba..2fb4799f 100644 --- a/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ShopPay/ShopPayButton.swift +++ b/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ShopPay/ShopPayButton.swift @@ -64,6 +64,7 @@ internal struct ShopPayButton: View { /// Internal_ wrapper component allows `ShopifyAcceleratedCheckouts.Configuration` to be /// DI into ShopPayViewController at init, avoiding optionality checks through ViewController @available(iOS 16.0, *) +@MainActor internal struct Internal_ShopPayButton: View { private var controller: ShopPayViewController private let cornerRadius: CGFloat? @@ -87,7 +88,7 @@ internal struct Internal_ShopPayButton: View { var body: some View { Button( action: { - Task { await controller.onPress() } + Task { @MainActor in await controller.onPress() } }, label: { HStack { diff --git a/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ShopPay/ShopPayViewController.swift b/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ShopPay/ShopPayViewController.swift index 6397589a..ab267fbb 100644 --- a/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ShopPay/ShopPayViewController.swift +++ b/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/ShopPay/ShopPayViewController.swift @@ -25,6 +25,7 @@ import ShopifyCheckoutKit import SwiftUI @available(iOS 16.0, *) +@MainActor class ShopPayViewController: WalletController { var eventHandlers: EventHandlers var client: (any CheckoutCommunicationProtocol)? diff --git a/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/WalletController.swift b/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/WalletController.swift index 7f5cfb65..2fefb997 100644 --- a/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/WalletController.swift +++ b/platforms/swift/Sources/ShopifyAcceleratedCheckouts/Wallets/WalletController.swift @@ -25,6 +25,7 @@ import ShopifyCheckoutKit import SwiftUI @available(iOS 16.0, *) +@MainActor class WalletController: ObservableObject { @Published var identifier: CheckoutIdentifier @Published var storefront: StorefrontAPIProtocol @@ -58,7 +59,6 @@ class WalletController: ObservableObject { } } - @MainActor func present(url: URL, client: (any CheckoutCommunicationProtocol)?) async throws { guard let topViewController = getTopViewController() else { throw ShopifyAcceleratedCheckouts.Error.invariant(expected: "topViewController") @@ -71,7 +71,6 @@ class WalletController: ObservableObject { ) } - @MainActor func getTopViewController() -> UIViewController? { guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let window = windowScene.windows.first