Hola lector
En un artículo 
anterior , hablé sobre el ciclo 
VIP de la arquitectura 
Clean Swift . Ahora tocaremos uno de los temas más importantes: la 
transición y la 
transferencia de datos entre escenas.

Teoría
El componente 
Router es responsable de la lógica de navegación y transferencia de datos, que es parte de la escena (opcional, por supuesto). Se inicializa en 
ViewController , junto con el 
Interactor y el 
Presentador .
El enrutador implementa dos protocolos: 
RoutingLogic y 
DataPassing , que completaremos con nuestra funcionalidad. 
RoutingLogic debe contener los métodos responsables de la transición a una escena específica. 
DataPassing contiene la variable 
dataStore , que se refiere al Protocol 
DataStore . 
Interactor Scenes implementa el protocolo 
DataStore y trabaja con las variables almacenadas en él. 
El enrutador contiene un enlace al 
ViewController de su escena.
Usando el enlace al 
ViewController , el 
enrutador salta entre las escenas. Para hacer esto, puede usar 
Segue o crear una escena a la que desea hacer una transición, mediante programación. El método utilizado no es importante, lo principal para nosotros es tener un enlace a una instancia de la clase 
ViewController a la que nos estamos cambiando.
Usando el enlace al 
DataStore, transferiremos datos desde el 
Interactor de una escena al 
Interactor de la escena a la que estamos cambiando. Y, como se mencionó anteriormente, es el 
enrutador el que necesita saber cómo hacer esto.
Practica
Por ejemplo, transferiremos el texto de TextField a Label de otra escena. Consideremos dos formas de transición entre escenas: según 
Segue y mediante programación.
La clase 
Router contiene 3 grupos semánticos de métodos:
- Métodos de implementación de RoutingLogic (routeTo)
- Métodos responsables de la navegación (navegar a, transición sin Segue)
- Métodos para la transferencia de datos (passDataTo, si hay datos para transferir)

Si hacemos una transición a través de 
Segue , por ejemplo, cuando se hace clic en un botón, en 
ViewController debemos anular el método prepare (for: sender :). Esta extensión le permitirá llamar automáticamente a los métodos del 
enrutador con el nombre de 
Segue .
La preparación de sobrescritura (para: remitente :) es opcional cuando se trabaja con Segue. Puede excluirlo del código y llamar a performSegue (withIdentifier: sender :) en el método Router . Preparar solo es necesario si necesita usar Segue junto con la transferencia de datos.|  | final class HomeViewController: UIViewController { | 
|  | // ... | 
|  |  | 
|  | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { | 
|  | // Segue | 
|  | if let scene = segue.identifier { | 
|  |  | 
|  | // , Router | 
|  | // router?.routeToNAME(segue:) | 
|  | let selector = NSSelectorFromString("routeTo\(scene)WithSegue:") | 
|  |  | 
|  | // , | 
|  | // Segue | 
|  | if let router = router, router.responds(to: selector) { | 
|  | router.perform(selector, with: segue) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // ... | 
|  | } | 
Ahora finalmente llegamos a lo más interesante: el código del 
enrutador . El ejemplo contiene comentarios, por lo que solo consideraremos los puntos clave.
En este 
enrutador, trabajamos con dos escenas: 
Inicio y 
Detalle . La transición desde la escena 
Home también se maneja de dos maneras: por 
Segue y mediante 
programación . Los datos se transfieren desde la escena 
Inicio a la escena 
Detalle .
Todos los métodos en el protocolo 
RoutingLogic deben nombrarse de acuerdo con el principio 
routeToNAME , donde 
NAME es el nombre del 
Segue (Identificador) que especificamos al trabajar con 
Storyboard . Esto es necesario no solo para la conveniencia y belleza del uso, sino también para nuestro selector de métodos en 
preparación (para: remitente :) ViewController , que redefinimos anteriormente.
También en la clase 
HomeRouter hay métodos que comienzan con 
navigationTo y 
passDataTo . Los primeros son responsables de la lógica de transición, mientras que los segundos son responsables de la transferencia de datos. Los métodos de navegación solo se crean si la transición se realiza mediante programación.
En el ejemplo, tenemos un 
método routeToDetail (segue :) . El parámetro 
segue es opcional ya que El método contiene una implementación que le permite llamarlo sin usar 
Segue . En ambos casos de transición, obtenemos valores no opcionales de nuestra escena 
HomeViewController y 
HomeDataStore'a Home , así como enlaces a la escena 
ViewController y 
DataStore Detail . Aquí vale la pena prestar atención al hecho de que 
detailDS es una variable y se pasa al método 
passDataToDetail usando el parámetro pass-through (inout). Esto es importante porque sin 
inout, tendremos que marcar todos los protocolos de 
DataStore como "posibles de implementar solo con clases" (protocolo DetailDataStore: class), y esto conlleva muchas dificultades, incluida la captura de enlaces fuertes.
|  |  | 
|  | import UIKit | 
|  |  | 
|  | /// @objc | 
|  | /// prepare View Controller'e | 
|  | @objc protocol HomeRoutingLogic { | 
|  | /// Detail View Controller | 
|  | func routeToDetail(segue: UIStoryboardSegue?) | 
|  | } | 
|  |  | 
|  | protocol HomeDataPassing { | 
|  | var dataStore: HomeDataStore? { get } | 
|  | } | 
|  |  | 
|  | final class HomeRouter: NSObject, HomeRoutingLogic, HomeDataPassing { | 
|  |  | 
|  | // MARK: - Private | 
|  |  | 
|  | // MARK: - Public | 
|  |  | 
|  | weak var viewController: HomeViewController? | 
|  | var dataStore: HomeDataStore? | 
|  |  | 
|  | // MARK: - HomeRoutingLogic | 
|  |  | 
|  | func routeToDetail(segue: UIStoryboardSegue?) { | 
|  | if let segue = segue { | 
|  | // | 
|  | // Segue | 
|  |  | 
|  | // Detail View Controller | 
|  | // Data Store Router'e | 
|  | guard | 
|  | let homeDS = dataStore, | 
|  | let detailVC = segue.destination as? DetailViewController, | 
|  | var detailDS = detailVC.router?.dataStore | 
|  | else { fatalError("Fail route to detail") } | 
|  |  | 
|  | // , , , | 
|  | // "" | 
|  | passDataToDetail(source: homeDS, destination: &detailDS) | 
|  | } else { | 
|  | // , | 
|  | // Segue | 
|  |  | 
|  | // Detail View Controller Storyboard'a | 
|  | // Data Store Router'e | 
|  | guard | 
|  | let viewController = viewController, | 
|  | let homeDS = dataStore, | 
|  | let storyboard = viewController.storyboard, | 
|  | let detailVC = storyboard.instantiateViewController(withIdentifier: "Detail") as? DetailViewController, | 
|  | var detailDS = detailVC.router?.dataStore | 
|  | else { fatalError("Fail route to detail") } | 
|  |  | 
|  | passDataToDetail(source: homeDS, destination: &detailDS) | 
|  |  | 
|  | // , "" | 
|  | navigateToDetail(source: viewController, destination: detailVC) | 
|  | } | 
|  | } | 
|  |  | 
|  | // MARK: - Navigation | 
|  |  | 
|  | private func navigateToDetail(source: HomeViewController, destination: DetailViewController) { | 
|  | source.navigationController?.pushViewController(destination, animated: true) | 
|  | } | 
|  |  | 
|  | // MARK: - Passing data | 
|  |  | 
|  | /// destination inout, | 
|  | /// Data Store | 
|  | private func passDataToDetail(source: HomeDataStore, destination: inout DetailDataStore) { | 
|  |  | 
|  | // HomeDataStore DetailDataStore | 
|  | destination.message = source.message | 
|  | } | 
|  | } | 
Conclusión
Eso es todo. ¡Gracias por leer hasta el final! A continuación, dejaré un enlace al proyecto si desea probar el artículo en acción.
Serie de artículos
- Descripción general de la arquitectura Clean Swift
- Enrutador y paso de datos en arquitectura Clean Swift (usted está aquí)
- Trabajadores de la arquitectura Clean Swift
- Pruebas unitarias en arquitectura Clean Swift
- Un ejemplo de una arquitectura simple de tienda en línea Clean Swift
Enlace al proyectoAyuda para escribir un artículo: 
Bastien