DEV Community

Cover image for Integrando SwiftUI em UIKit e implementando View com Coordinator
Lys
Lys

Posted on

Integrando SwiftUI em UIKit e implementando View com Coordinator

É a primeira vez que trabalho em um projeto que está usando SwiftUI para implementar novos fluxos, mas como os fluxos são majoritariamente UIKit, é preciso fazer uma pequena integração com na hora de exibir um fluxo em SwiftUI.

Para simular um fluxo de navegação entre telas, vamos pensar que a tela com as opções é o nosso fluxo inicial feito em UIKit (programaticamente/view code) e a tela de imóveis agendados que será exibida, é a nossa view em SwiftUI.

Gif de gravação de tela mostrando ação do botão

Para um Coordinator inicial, pensaremos em algo como

import UIKit

protocol PropertyCoordinatorProtocol: AnyObject {
    func navigateToSchedule()
}

class PropertyCoordinator: PropertyCoordinatorProtocol {
    private var navigationController: UINavigationController
    private let viewModel: PropertyViewModel

    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
        self.viewModel = PropertyViewModel()
        viewModel.coordinator = self
    }

    func start() {
        let viewController = PropertyViewController(viewModel: viewModel)
        navigationController.pushViewController(viewController, animated: false)
    }
}
Enter fullscreen mode Exit fullscreen mode

Para exibir a view, criaremos um método navigateToSchedule que fará a apresentação a partir da nossa Navigation Controller.

func navigateToSchedule() {
    let scheduleViewController = ScheduleViewController()
    navigationController.present(scheduleViewController, animated: true)
}
Enter fullscreen mode Exit fullscreen mode

Ao criar ScheduleViewController, a instancia de UIHostingController é o que permite incorporar uma view SwiftUI dentro de um layout UIKit.

private lazy var mainView: UIView = {
    let view = ScheduleView()
    let controller = UIHostingController(rootView: view)
    addChild(controller) 
    controller.view.translatesAutoresizingMaskIntoConstraints = false
    return controller.view
}()
Enter fullscreen mode Exit fullscreen mode

O addChild(controller) adiciona o UIHostingController como filho do controlador atual, o que é necessário para gerenciar corretamente os ciclos de vida das views dentro de um view controller pai.

A view controller exibida será assim

import UIKit
import SwiftUI

final public class ScheduleViewController: UIViewController {
    private lazy var mainView: UIView = {
        let view = ScheduleView()
        let controller = UIHostingController(rootView: view)
        addChild(controller) 
        controller.view.translatesAutoresizingMaskIntoConstraints = false
        return controller.view
    }()

    public override func loadView() {
        self.view = UIView()
        view.backgroundColor = .clear
        setupHierarchy()
        setupConstraints()
    }

    func setupHierarchy() {
        view.addSubview(mainView)
    }

    func setupConstraints() {
        guard let superview = self.mainView.superview else { return }

        NSLayoutConstraint.activate([
            mainView.topAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.topAnchor),
            mainView.bottomAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.bottomAnchor),
            mainView.trailingAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.trailingAnchor),
            mainView.leadingAnchor.constraint(equalTo: superview.safeAreaLayoutGuide.leadingAnchor)
        ])
    }

    public override func viewDidLoad() {
        super.viewDidLoad()
    }

    public override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        mainView.frame = view.bounds 
    }
}
Enter fullscreen mode Exit fullscreen mode

E na View Controller principal, teremos um método que será chamado quando o botão for clicado

@objc func goToScheduleView() {
    viewModel.showScheduleView()
}
Enter fullscreen mode Exit fullscreen mode

E a view model terá um método que chamará o Coordinator

func showScheduleView() {
    coordinator?.navigateToSchedule()
}
Enter fullscreen mode Exit fullscreen mode

Código no github

Top comments (0)