Как перейти из SwiftUI View в UIKit UIViewController - PullRequest
1 голос
/ 19 февраля 2020

На данный момент у меня есть приложение, созданное полностью с использованием UIKit. Тем не менее, я sh смог начать реализацию некоторых представлений SwiftUI для замены некоторых контроллеров UIViewController.

Я смог сделать это для перехода от UIViewController к представлению SwiftUI на нажатие кнопки:

    @IBAction func buttonTapped(_ sender: Any) {
        let newView = UIHostingController(rootView: SwiftUIView(viewObj: self.view, sb: self.storyboard, dismiss: self.dismiss) )
        view.window?.rootViewController = newView
        view.window?.makeKeyAndVisible()
    }

Мой вопрос заключается в том, как бы перейти от одного представления SwiftUI к UIViewController? (Поскольку остальная часть приложения находится в UIKit)? У меня есть кнопка в SwiftUI View, чтобы вернуться к UIViewController на кране. Я пробовал:

  1. Передача объектов view и storyboard в SwiftUI View, а затем вызывая что-то похожее на код выше, чтобы изменить текущий контроллер представления. Тем не менее, при попытке на симуляторе ничего не происходит.
  2. Использование .present для модального отображения SwiftUI View. Это работает, и я могу разрешить SwiftUI View самому .dismiss. Тем не менее, это работает только модально, и я надеюсь сделать эту работу правильно (например, изменить экран)

Вот мой простой SwiftUI View:

struct SwiftUIView: View {
    var viewObj:UIView? // Perhaps use this for transition back?
    var sb:UIStoryboard?
    var dismiss: (() -> Void)?

    var body: some View {

        Button(action: {
            // Do something here to Transition
        }) {
            Text("This is a SwiftUI view.")
        }
    }
}

У меня проблемы понимание того, как правильно интегрировать SwiftUI в UIKit NOT с другой стороны, и я не уверен, является ли ответ UIViewControllerRepresentable на это. Любое решение этого вопроса, альтернативы или полезные знания очень ценится. Еще раз спасибо!

Ответы [ 2 ]

1 голос
/ 19 февраля 2020

Ciao,

Я пытался следовать вашему подходу, используя обратные вызовы закрытия.

struct SwiftUIView: View {
    var dismiss: (() -> Void)?
    var present: (()->Void)?

    var body: some View {
        VStack(spacing: 20) {
            Button(action: {
                self.dismiss?()
            }) {
                Text("Dismiss me")
            }
            Button(action: {
                self.present?()
            }) {
                Text("Present some UIViewController")
            }
        }
    }
}

Когда вы представляете свой UIHostingController, вы хотите реализовать 2 обратных вызова закрытия:

@IBAction func buttonTapped(_ sender: Any) {
    let hostingController = UIHostingController(rootView: SwiftUIView())
    hostingController.rootView.dismiss = {
        hostingController.dismiss(animated: true, completion: nil)
    }
    hostingController.rootView.present = {
        let destination = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "VC_TO_PRESENT")
        hostingController.present(destination, animated: true, completion: nil)
    }

    present(hostingController, animated: true, completion: nil)
}
0 голосов
/ 19 февраля 2020

Вы можете сделать то же самое, только в зеркальном порядке, как показано ниже (неуклюже) ...

    Button(action: {
        if let vc = self.sb?.instantiateViewController(withIdentifier: "some_identifier") {
            self.viewObj?.window?.rootViewController = vc
            // or via present as alternate
            // self.viewObj?.window?.rootViewController.present(vc, animated: true, completion: nil)
        }
    }) {
...