Kio
Kio

Reputation: 116

passing a value from swift viewcontroller to swiftui and then back again

so using UIHostingController to open a swiftUI view from a old view controller. going to do some editing in say fancy swiftui interface, then when I dismiss swiftui view want to pass the edited value back to original view controller.

I can get the value going over to the swiftui view but thinking how to get it back? looking for quick direction to go with. is it protocols, observables. what is the correct way

passing value over from VC to SwiftUI with say this: but getting value back ??

var selectedValue:String = "this is the selected text to edit"

let swiftUIView = swiftUIEditView(valueSelected: selectedValue)

let hostingController = UIHostingController(rootView: swiftUIView)
present(hostingController, animated: true, completion: nil) 

Upvotes: 0

Views: 816

Answers (1)

aheze
aheze

Reputation: 30318

There's a lot of ways you can do this, but I prefer closures. You can pass back the value using the dismissedWithString closure, like this:

struct SwiftUIEditView: View {
    
    @State var valueSelected: String
    var dismissedWithString: ((String) -> Void)? /// closure here!
    
    var body: some View {
        VStack {
            TextField("Text field", text: $valueSelected)
                .multilineTextAlignment(.center)
            
            Button(action: {
                dismissedWithString?(valueSelected) /// call the closure and pass in the text
            }) {
                Text("Return string and dismiss")
            }
        }
    }
}

Then your View Controller will be something like this:

class ViewController: UIViewController {
    var selectedValue: String = "this is the selected text to edit"

    func presentEditView() {
        
        var viewController: UIViewController?
        
        let contentView = SwiftUIEditView(valueSelected: selectedValue) { [weak self] returnedString in
            
            /// dismiss UIHostingController - it's a trailing closure, so you don't need to put the `dismissSelf`
            viewController?.dismiss(animated: true, completion: nil)
            
            self?.selectedValue = returnedString /// assign
            print(returnedString) /// will be the value
        }
        
        viewController = UIHostingController(rootView: contentView)
        
        if let vc = viewController { /// viewController will never be nil, but I don't like to force-unwrap
            self.present(vc, animated: true, completion: nil)
        }
    }
}

Upvotes: 3

Related Questions