Post

UIHostingController

SwiftUI ofrece un UIViewController para UIKit, que le permite gestionar la integración de vistas hechas en SwiftUI y presentarlas como otro UIViewController.

En el ejemplo tendríamos una vista de ProfileView con una propiedad opcional delegate conformada con ButtonDelegate, que se encargará de conectar la acción con el UIViewController, mediante un Button.

El botón de Salir avisa al delegado que ha sido pulsado. (1)

El protocolo ButtonDelegate que es del tipo AnyObject, una clase. (2)

En el UIViewController se instancia ProfileView, siendo él mismo el delegado, y se añade a la view como una subvista y del tipo UIHostingController, con sus constraints correspondientes.

Al conformar ProfileVC con ButtonDelegate nos obliga a añadir el método tappedExitAppButton, que al pulsar mostrará al usuario la pantalla de Login.

De esta manera podemos sustituir vistas de nuestros proyectos de UIKit con vistas hechas en SwiftUI de una manera muy sencilla.

ProfileViewController

final class ProfileVC: UIViewController, ButtonDelegate {
    var screen: ProfileScreen?
    override func loadView() {
        screen = ProfileScreen()
        view = screen
    }
    override func viewWillAppear(_ animated: Bool) {
        navigationController?.isNavigationBarHidden = true
    }
    override func viewDidLoad() {
        super.viewDidLoad()
        let profileView = ProfileView(delegate: self)
        let hostingController = UIHostingController(rootView: profileView)
        
        addChild(hostingController)
        view.addSubview(hostingController.view)
        
        hostingController.view.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
                    hostingController.view.topAnchor.constraint(equalTo: view.topAnchor),
                    hostingController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
                    hostingController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
                    hostingController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor)
                ])
        hostingController.didMove(toParent: self)
    }
    func tappedExitAppButton() {
        let vc = LoginVC()
        vc.modalPresentationStyle = .fullScreen
        present(vc, animated: true)
    }
}

ProfileView

extension ProfileView {
    init(delegate: ButtonDelegate?) {
        image = Image("nft")
        profeileImage = Image("user")
        name = "User Profile"
        user = "@userProfile"
        buttonText = "Salir"
        self.delegate = delegate
    }
}

protocol ButtonDelegate: AnyObject {
    func tappedExitAppButton()
}