4

I have got a SwiftUI modal view which I am calling from main UIKit view. I want to add a dismiss button to my modal view. As I can tell, there is no @State variables in UIKit, so I am creating a separate SwiftUI view to store my @State variable but for some reason it is not working. How should I fix this?

My code inside main ViewController:

var hack = StateInUIKitHack()
hack.modalIsPresented = true
let vc = UIHostingController(rootView: MoodCardView(isPresented: hack.$modalIsPresented, entryIndex: entryIndex, note: moodEntries[entryIndex].note ?? ""))
self.present(vc, animated: true, completion: nil)

StateInUIKitHack struct:

struct stateInUIKitHack: View {
     @State var modalIsPresented = false

    var body: some View {
        Text("Hello, World!")
    }
} 

Inside MoodCardView.swift I have:

 @Binding var isPresented: Bool

And if I create my modal sheet from another SwiftUI View the classical way it dismisses OK, but I need to create it from the UIKit view.

1 Answer 1

10

Here is a demo of possible approach. Tested with Xcode 11.4 / Playground

enter image description here

Complete playground code:

import UIKit
import SwiftUI
import PlaygroundSupport

class ViewModel {
    var closeAction: () -> Void = {}
}

struct ModalView: View {
    var vm: ViewModel

    var body: some View {
        VStack {
            Text("I'm SwfitUI")
            Button("CloseMe") {
                self.vm.closeAction()
            }
        }
    }
}

class MyViewController : UIViewController {

    override func loadView() {
        let view = UIView()
        view.backgroundColor = .white

        let button = UIButton(type: .roundedRect)
        button.setTitle("ShowIt", for: .normal)
        button.addTarget(self, action: #selector(MyViewController.showModal(_:)), for: .touchDown)

        view.addSubview(button)

        button.translatesAutoresizingMaskIntoConstraints = false
        button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        button.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        self.view = view
    }

    @objc func showModal(_ : Any?) {
        let bridge = ViewModel()
        let vc = UIHostingController(rootView: ModalView(vm: bridge))
        bridge.closeAction = { [weak vc] in
            vc?.dismiss(animated: true)
        }
        self.present(vc, animated: true, completion: nil)
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.