纯SwiftUI项目中如何正确展示PKPaymentAuthorizationViewController?现有方案遇阻
解决SwiftUI中Apple Pay展示的布局与触发问题
嘿,我太熟悉你遇到的这个问题了——用sheet展示Apple Pay原生控制器时布局拉胯,换overlay虽然样式对了但按钮点了没反应,而且旧的present方法还失效了。这其实是SwiftUI和UIKit交互时的常见适配问题,我给你两个靠谱的解决方案:
方案一:搞定Overlay的触发逻辑
Overlay本身默认是隐藏的,你需要用状态变量精准控制它的显隐,还要确保Apple Pay完成后能把状态重置回来。先修改你的ContentView:
public struct ContentView: View { @ObservedObject var model: RootViewModel @State private var tappedDonate = false public var body: some View { Button(action: { tappedDonate = true }, label: { Text("Donate") .frame(width: 300, height: 44, alignment: .center) }) .frame(width: 300, height: 20, alignment: .center) .padding() .background(Color.black) .foregroundColor(.white) .cornerRadius(22) // 用状态控制overlay的显示与隐藏 .overlay(alignment: .center) { if tappedDonate { ApplePayWrapper(request: model.buildApplePayment(), isPresented: $tappedDonate) .background(Color.clear) } } } public init(model: RootViewModel) { self.model = model } }
然后给你的ApplePayWrapper加个绑定变量,用来通知父视图同步关闭状态:
struct ApplePayWrapper: UIViewControllerRepresentable { let request: PKPaymentRequest @Binding var isPresented: Bool // 新增绑定,同步显隐状态 func makeUIViewController(context: Context) -> PKPaymentAuthorizationViewController { guard let vc = PKPaymentAuthorizationViewController(paymentRequest: request) else { // 处理请求无效的情况,返回空VC或做错误提示 return UIViewController() } vc.delegate = context.coordinator return vc } func updateUIViewController(_ uiViewController: PKPaymentAuthorizationViewController, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, PKPaymentAuthorizationViewControllerDelegate { let parent: ApplePayWrapper init(_ parent: ApplePayWrapper) { self.parent = parent } // 支付完成/取消时,关闭VC并重置状态 func paymentAuthorizationViewControllerDidFinish(_ controller: PKPaymentAuthorizationViewController) { controller.dismiss(animated: true) { self.parent.isPresented = false } } // 实现支付授权逻辑,根据实际业务调整 func paymentAuthorizationViewController(_ controller: PKPaymentAuthorizationViewController, didAuthorizePayment payment: PKPayment, handler completion: @escaping (PKPaymentAuthorizationResult) -> Void) { // 这里处理支付验证逻辑,比如调用后端接口 completion(PKPaymentAuthorizationResult(status: .success, errors: nil)) } } }
这样点击按钮后overlay会正常弹出Apple Pay,支付完成后状态自动重置,下次点击依然能正常触发。
方案二:修复Sheet的布局问题
如果你还是想用sheet,问题大概率是原生VC没有适配SwiftUI的sheet容器。试试给ApplePayWrapper加上忽略安全区域的设置:
.sheet(isPresented: $tappedDonate) { ApplePayWrapper(request: model.buildApplePayment()) .background(Color.clear) .edgesIgnoringSafeArea(.all) }
另外别忘了检查PKPaymentRequest的配置——比如merchantIdentifier是否和开发者后台一致,supportedNetworks有没有添加全,这些配置错误也会导致展示异常。
关键提醒
- 不管用哪种方式,都要确保
ApplePayWrapper的代理回调正确触发,不然状态变量会一直停留在true,导致后续点击按钮无反应 - 测试时一定要用支持Apple Pay的设备或配置好的模拟器,普通模拟器可能会出现各种奇怪的问题
内容的提问来源于stack exchange,提问作者Lucas van Dongen
相关产品推荐
相关产品推荐

