You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI Apple Pay Button在UIKit项目编译失败求助

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 14:23:16