[SOLVED] Integrating Persona SDK in a SwiftUI View

Issue

This Content is from Stack Overflow. Question asked by Berry Blue

I’m trying it integrate the Person SDK v2 in a SwiftUI view. It’s setup for UIKit to present from a specific UIViewController. Here is my code.
https://docs.withpersona.com/docs/ios-sdk-v2-integration-guide

I’m not sure how to call my present function from SwiftUI. The SDK is setup so when you create that Inquiry object it triggers it’s nav to present on the view controller.

struct PersonaInquiry: UIViewControllerRepresentable {

    private var viewController = UIViewController()
    private var coordinator = Coordinator()
    
    class Coordinator: NSObject, InquiryDelegate {
        func inquiryComplete(inquiryId: String, status: String, fields: [String : Persona2.InquiryField]) {
            
        }
        
        func inquiryCanceled(inquiryId: String?, sessionToken: String?) {
            
        }
        
        func inquiryError(_ error: Error) {
            
        }
    }
    
    func makeUIViewController(context: Context) -> UIViewController {
        return viewController
    }
    
    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
        
    }
    
    func present(templateId: String) {
        let config = InquiryConfiguration(templateId: templateId)
        
        // Create the inquiry with the view controller
        // as the delegate and presenter.
        Inquiry(config: config, delegate: coordinator).start(from: viewController)
    }
    
    func makeCoordinator() -> Coordinator {
        return coordinator
    }
}

struct PersonaInquiry_Previews: PreviewProvider {
    static var previews: some View {
        PersonaInquiry()
    }
}



Solution

Here’s an example

ContentView:

struct ContentView: View {
    
    @State private var isPresentingSDK = false
    @State private var message = ""
    
    var body: some View {
        VStack {
            Button(
                action: {
                    isPresentingSDK.toggle()
                },
                label: {
                    Text("Launch Inquiry from SwiftUI 🚀")
                        .foregroundColor(Color.white)
                        .padding()
                }
            )
            .buttonStyle(.borderedProminent)
            .buttonBorderShape(.capsule)
            .fullScreenCover(
                isPresented: $isPresentingSDK,
                onDismiss: {
                    // Do nothing
                },
                content: {
                    InquirySDKWrapper(
                        inquiryComplete: { inquiryId, status, fields in
                            self.message = """
                                Inquiry Complete
                                Inquiry ID: \(inquiryId)
                                Status: \(String(describing: status))
                            """
                        },
                        inquiryCanceled: { inquiryId, sessionToken in
                            self.message = "🤷‍♀️ Inquiry Cancelled"
                        },
                        inquiryErrored: { error in
                            self.message = """
                                💀 Inquiry Error
                                \(error.localizedDescription)
                            """
                        }
                    )
                }
            )
            
            Text(message)
                .multilineTextAlignment(.center)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

InquirySDKWrapper:

import Persona2
import SwiftUI
import UIKit

struct InquirySDKWrapper: UIViewControllerRepresentable {
    
    /// The wrapper VC presents the SDK and acts as its delegate.
    /// The delegate methods in turn call the callbacks in the WrapperDelegate
    private let wrapperVC: WrapperViewController
    
    /// Pass in the callbacks for each delegate method
    init(
        inquiryComplete: @escaping (String, String, [String: InquiryField]) -> Void,
        inquiryCanceled: @escaping (_ inquiryId: String?, _ sessionToken: String?) -> Void,
        inquiryErrored: @escaping (_ error: Error) -> Void
    ) {
        wrapperVC = WrapperViewController()
        wrapperVC.inquiryComplete = inquiryComplete
        wrapperVC.inquiryCanceled = inquiryCanceled
        wrapperVC.inquiryErrored = inquiryErrored
    }
    
    func makeUIViewController(context: Context) -> some UIViewController {
        return wrapperVC
    }
    
    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) {
        // Do nothing
    }
}


final class WrapperViewController: UIViewController {
    
    private var isPresenting = false
    
    // The callbacks
    var inquiryComplete: ((_ inquiryId: String, _ status: String, _ fields: [String: InquiryField]) -> Void)!
    var inquiryCanceled: ((_ inquiryId: String?, _ sessionToken: String?) -> Void)!
    var inquiryErrored: ((_ error: Error) -> Void)!
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        
        // Otherwise this would trigger once the SDK exits too
        guard !isPresenting else { return }
        
        let inquiry = Inquiry(
            config: InquiryConfiguration(
                templateId: "YOUR TEMPLATE ID HERE"
            ),
            delegate: self
        )

        inquiry.start(from: self)
        
        isPresenting = true
    }
}

extension WrapperViewController: InquiryDelegate {

    func inquiryComplete(inquiryId: String, status: String, fields: [String: InquiryField]) {
        inquiryComplete(inquiryId, status, fields)
        dismiss(animated: true, completion: nil)
    }

    func inquiryCanceled(inquiryId: String?, sessionToken: String?) {
        inquiryCanceled(inquiryId, sessionToken)
        dismiss(animated: true, completion: nil)
    }

    func inquiryError(_ error: Error) {
        inquiryErrored(error)
        dismiss(animated: true, completion: nil)
    }
}


This Question was asked in StackOverflow by Berry Blue and Answered by Jacob Lange It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?