micma
micma

Reputation: 223

How to create a wrapper for PKPaymentButton

I'm trying to implement the PKPaymentButton in SwiftUI, but I cannot figure out how to create a wrapper for the PKPaymentButton. My code is below:

struct ApplePayButton: UIViewRepresentable {

    func makeUIViewController(context: Context) -> PKPaymentButton {
        return PKPaymentButton.init()
    }

    func updateUIView(_ uiView: ApplePayButton.UIViewType, context: UIViewRepresentableContext<ApplePayButton>) {
        //
    }
}

I am getting the following errors:

Has anyone been able to do this, or does anyone have a better way of implementing Apple Pay in SwiftUI?

Upvotes: 1

Views: 1364

Answers (2)

IcyHovercraft
IcyHovercraft

Reputation: 73

This took me FOREVER to figure out, so maybe someone will find this helpful:

Basically, it's not enough to just wrap the button in a UIViewRepresentable. You have to put that in a ButtonStyle, and then style a SwiftUI button with it. If you don't, it seems like your payment sheet will break! I'm not sure why this is true, but here's the code as it should work:

import SwiftUI
import UIKit
import PassKit

struct PaymentButton: View {
    var body: some View {
        Button(action: { /* Custom payment code here */ }, label: { EmptyView() } )
            .buttonStyle(PaymentButtonStyle())
    }
}

struct PaymentButtonStyle: ButtonStyle {
    func makeBody(configuration: Self.Configuration) -> some View {
        return PaymentButtonHelper()
    }
}  
    
struct PaymentButtonHelper: View {
    var body: some View {
        PaymentButtonRepresentable()
            .frame(minWidth: 100, maxWidth: 400)
            .frame(height: 60)
            .frame(maxWidth: .infinity)
    }
}

extension PaymentButtonHelper {
    struct PaymentButtonRepresentable: UIViewRepresentable {
    
    var button: PKPaymentButton {
        let button = PKPaymentButton(paymentButtonType: .buy, paymentButtonStyle: .black) /*customize here*/
        button.cornerRadius = 4.0 /* also customize here */
        return button
    }
     
    func makeUIView(context: Context) -> PKPaymentButton {
        return button
    }
    func updateUIView(_ uiView: PKPaymentButton, context: Context) { }
}

Usage would then be:

struct ContentView: View {
    var body: some View {
        PaymentButton()
    }
}

Upvotes: 2

Asperi
Asperi

Reputation: 257729

The declaration should be like the following:

import SwiftUI
import UIKit
import PassKit

struct ApplePayButton: UIViewRepresentable {


    func makeUIView(context: Context) -> PKPaymentButton {
        return PKPaymentButton()
    }

    func updateUIView(_ uiView: PKPaymentButton, 
                 context: UIViewRepresentableContext<ApplePayButton>) {
        //
    }
}

Upvotes: 2

Related Questions