Patrón de coordinador en iOS

Feb 26 2023
¡Hola amigos! ¿Qué es un coordinador? El coordinador es un componente del sistema que contiene la lógica de navegación de una aplicación. El patrón fue introducido por Soroush Khanlou.

¡Hola amigos!

¿Qué es un coordinador?

El coordinador es un componente del sistema que contiene la lógica de navegación de una aplicación. El patrón fue introducido por Soroush Khanlou .

¿Por qué necesitamos un coordinador?

El beneficio de usar el patrón coordinador es que eliminamos la responsabilidad de la navegación de los controladores. De esta manera podemos aumentar su reutilización también podemos tener la navegación de la aplicación en un lugar central, ya sea que tengamos un coordinador o tengamos un coordinador principal con niños.

Desacoplar los controladores de vista de la navegación de la aplicación puede aumentar la legibilidad del proyecto. En aplicaciones más grandes, tener la navegación de la aplicación en un componente separado del sistema es esencial, especialmente si hay equipos de funciones.

El objetivo es poder cambiar la navegación de la lógica fácilmente según la situación. Por ejemplo, diferentes usuarios pueden tener diferentes flujos o usuarios de iPad o pruebas A/B de forma aislada.

Características principales de un Coordinador.

  • Un coordinador puede tener muchos ViewControllers.
  • Los coordinadores tienen un método de inicio donde muestran el ViewController inicialmente.
  • Los ViewControllers tienen una referencia a un Coordinador.
  • El coordinador tiene una serie de coordinadores de niños.
  • Los coordinadores de niños tienen una referencia a su padre.

protocol Coordinator: AnyObject {
    var childCoordinators: [Coordinator] { get set }
    var navigationController: UINavigationController { get set }
    
    func start()
}

final class AppCoordnator: Coordinator {
    // 1
    var childCoordinators = [Coordinator]()
    
    // 2
    var navigationController: UINavigationController
        
    // 3
    init(navigationController: UINavigationController) {
        self.navigationController = navigationController
    }
    
    // 4
    func start() {
        let controller = StartViewController() 
        controller.coordinator = self
        navigationController.pushViewController(controller, animated: true)
    }
}

  1. El elemento de la interfaz de usuario donde se incrustarán los ViewControllers.
  2. Inyectado el elemento UI en el constructor.
  3. El método de inicio es donde ocurre la inicialización del ViewController y la conexión con el navigationController.

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

    // ...

    let navigationController = UINavigationController()
    let appCoordinator = AppCoordinator(navigationController: navigationController)
    appCoordinator.applicationRunnerDelegate = self
    appCoordinator.start()

    window?.rootViewController = appCoordinator.navigationController
    // ... 
}

Coordinadores con UITabBarController

Para beneficiarnos del patrón de coordinador cuando tenemos un UITabBarController como componente principal de la interfaz de usuario de la aplicación, debemos crear un coordinador para cada pestaña. Vea el siguiente ejemplo:

final class MainTabBarController: UITabBarController {
    
    private let dashboardCoordinator: DashboardCoordnator
    private let settingsCoordinator: SettingsCoordnator

    init() {
        self.dashboardCoordinator = DashboardCoordnator(navigationController: NavigationController())
        self.settingsCoordinator = SettingsCoordnator(navigationController: NavigationController())
        super.init(nibName: nil, bundle: nil)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        // ...

        viewControllers = [
            makeDashboardCoordinator(),
            makeSettingsCoordinator()
        ]
    }
    
    private func makeDashboardCoordinator() -> UINavigationController {
        let tabImage = "dashboard_tab_icon"

        let icon = UITabBarItem(title: "DASHBOARD",
                                image: UIImage(named: tabImage)?.withRenderingMode(.alwaysOriginal),,
                                selectedImage: UIImage(named: tabImage))
        dashboardCoordinator.navigationController.tabBarItem = icon
        dashboardCoordinator.start()
        return dashboardCoordinator.navigationController
    }
    
    private func makeSettingsCoordinator() -> UINavigationController {
        let tabImage = "settings_tab_icon"

        let icon = UITabBarItem(title: "SETTINGS",
                                image: UIImage(named: tabImage)?.withRenderingMode(.alwaysOriginal),
                                selectedImage: UIImage(named: tabImage))
        settingsCoordinator.navigationController.tabBarItem = icon
        settingsCoordinator.start()
        return settingsCoordinator.navigationController
    }
}

Separar la lógica de navegación de ViewControllers aumenta la cohesión de clase y reduce el acoplamiento del sistema. Mantiene la lógica de navegación en un lugar central y mejora la reutilización y la capacidad de prueba.

Para cualquier comentario o sugerencia o cualquier otra cosa...

Vamos a conectar:

Instagram:https://www.instagram.com/gvardikos/

Linkedin:https://www.linkedin.com/in/george-vardikos-b0b199b0/

Correo electrónico: [email protected]