SwiftUI Apple Pay Button在UIKit项目编译失败求助
问题描述
我开发了一款SwiftUI Apple Pay Button,在SwiftUI项目及新建的UIKit空白项目中均可正常编译运行,但在公司现有UIKit项目中使用ApplePayButtonRepresentable代码时编译失败,报错信息如下:
Type 'ApplePayButton.ApplePayButtonRepresentable' does not conform to protocol 'UIViewRepresentable'
尝试使用类型别名后仍无法解决,还出现新错误:
Value of type 'Context' has no member 'coordinator'
相关代码:
extension ApplePayButton { struct ApplePayButtonRepresentable: UIViewRepresentable { var action: () -> Void func makeUIView(context: Context) -> UIView { context.coordinator.button } func updateUIView(_ rootView: UIView, context: Context) { context.coordinator.action = action } func makeCoordinator() -> Coordinator { Coordinator(action: action) } } final class Coordinator: NSObject { var action: () -> Void var button = PKPaymentButton(paymentButtonType: .buy, paymentButtonStyle: .black) init(action: @escaping () -> Void) { self.action = action super.init() button.addTarget(self, action: #selector(callback(_:)), for: .touchUpInside) } @objc func callback(_ sender: Any) { action() } } }
解决方案
1. 显式指定UIViewRepresentable的关联类型
现有项目大概率存在命名冲突(比如自定义了同名的Context类型),显式声明关联类型可解决:
extension ApplePayButton { struct ApplePayButtonRepresentable: UIViewRepresentable { // 显式指定关联类型,避免命名冲突 typealias UIViewType = UIView typealias Context = UIViewRepresentableContext<ApplePayButtonRepresentable> var action: () -> Void func makeUIView(context: Context) -> UIView { context.coordinator.button } func updateUIView(_ rootView: UIView, context: Context) { context.coordinator.action = action } func makeCoordinator() -> Coordinator { Coordinator(action: action) } } // Coordinator代码保持不变 final class Coordinator: NSObject { var action: () -> Void var button = PKPaymentButton(paymentButtonType: .buy, paymentButtonStyle: .black) init(action: @escaping () -> Void) { self.action = action super.init() button.addTarget(self, action: #selector(callback(_:)), for: .touchUpInside) } @objc func callback(_ sender: Any) { action() } } }
2. 排查项目命名冲突
公司现有项目可能自定义了Context类型,和SwiftUI的UIViewRepresentable.Context别名冲突:
- 全局搜索项目中是否有自定义的
Context类/结构体,若有则重命名该类型,或者在使用时加上命名空间(比如SwiftUI.Context) - 直接在方法参数中使用完全限定名:
func makeUIView(context: UIViewRepresentableContext<ApplePayButtonRepresentable>) -> UIView { context.coordinator.button } func updateUIView(_ rootView: UIView, context: UIViewRepresentableContext<ApplePayButtonRepresentable>) { context.coordinator.action = action }
3. 确认必要框架已导入
确保项目文件中导入了PassKit和SwiftUI:
import PassKit import SwiftUI
4. 简化实现(可选)
若不需要通过Coordinator管理按钮实例,可直接返回PKPaymentButton,减少复杂度:
extension ApplePayButton { struct ApplePayButtonRepresentable: UIViewRepresentable { typealias UIViewType = PKPaymentButton var action: () -> Void func makeUIView(context: Context) -> PKPaymentButton { let button = PKPaymentButton(paymentButtonType: .buy, paymentButtonStyle: .black) button.addTarget(context.coordinator, action: #selector(context.coordinator.callback(_:)), for: .touchUpInside) return button } func updateUIView(_ button: PKPaymentButton, context: Context) { context.coordinator.action = action } func makeCoordinator() -> Coordinator { Coordinator(action: action) } final class Coordinator: NSObject { var action: () -> Void init(action: @escaping () -> Void) { self.action = action } @objc func callback(_ sender: Any) { action() } } } }
内容的提问来源于stack exchange,提问作者CableGuy
相关产品推荐
相关产品推荐

