swiftuiuikitapplepaypasskit

How to properly present PKPaymentAuthorizationViewController in a SwiftUI only project?


I have visited this answer already and the present method proposed here doesn't work (anymore?). When I use a UIViewControllerRepresentable and then show it as a sheet it looks pretty awful:

Screenshot UIViewControllerRepresentable sheet

If I use overlay it looks exactly like I want it to looks but overlay cannot be triggered from a Button.

Here is the (condensed) code:

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)
            .sheet(isPresented: $tappedDonate) {
                ApplePayWrapper(request: model.buildApplePayment())
                    .background(Color.clear)
            }
    }

    public init(model: RootViewModel) {
        self.model = model
    }
}

Solution

  • I'm not 100% convinced this is the best way to do it, but I managed to make it work visually like I intended it to work using a ZStack:

    
            ZStack {           
                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)
                if tappedDonate {
                    ApplePayWrapper(request: model.buildApplePayment())
                }
            }
    

    Note that you still need to hook up the cancel button as well as the regular dismiss by tapping outside through the delegate, otherwise the underlying UI with the button does not respond to touch again.