Bonjour lecteur!
Dans un article 
précédent , j'ai parlé du cycle 
VIP de l'architecture 
Clean Swift . Nous allons maintenant aborder l'un des sujets les plus importants - la 
transition et le 
transfert de données entre les scènes.

Théorie
Le composant 
Router est responsable de la logique de navigation et de transfert de données, qui fait partie de la scène (facultatif bien sûr). Il est initialisé dans le 
ViewController , avec l' 
Interactor et le 
Presenter .
Le routeur implémente deux protocoles - 
RoutingLogic et 
DataPassing , que nous remplirons de nos fonctionnalités. 
RoutingLogic doit contenir les méthodes responsables de la transition vers une scène spécifique. 
DataPassing contient la variable 
dataStore , qui fait référence au Protocol 
DataStore . 
Interactor Scenes implémente le protocole 
DataStore et fonctionne avec les variables qui y sont stockées. 
Le routeur lui-même contient un lien vers le 
ViewController de sa scène.
En utilisant le lien vers le 
ViewController , le 
routeur saute entre les scènes. Pour ce faire, vous pouvez utiliser 
Segue ou créer une scène vers laquelle vous souhaitez effectuer une transition, par programme. La méthode utilisée n'est pas importante, l'essentiel pour nous est d'avoir un lien vers une instance de la classe 
ViewController vers laquelle nous 
basculons .
En utilisant le lien vers le 
DataStore, nous transférerons les données de l' 
interacteur d' une scène vers l' 
interacteur de la scène vers laquelle nous basculons. Et, comme mentionné précédemment, c'est le 
routeur qui doit savoir comment procéder.
Pratique
Par exemple, nous allons transférer le texte de TextField vers Label d'une autre scène. Considérons deux façons de transition entre les scènes - selon 
Segue et par programme.
La classe 
Router contient 3 groupes sémantiques de méthodes:
- Méthodes de l' implémentation de RoutingLogic (routeTo)
- Méthodes responsables de la navigation (naviguer vers, transition sans Segue)
- Méthodes de transfert de données (passDataTo, s'il existe des données à transférer)

Si nous effectuons une transition via 
Segue , par exemple, lorsqu'un bouton est cliqué, alors dans 
ViewController, nous devons remplacer la méthode prepare (for: sender :). Cette extension vous permettra d'appeler automatiquement des méthodes depuis le 
routeur sous le nom de 
Segue .
Remplacer préparer (pour: expéditeur :) est facultatif lorsque vous travaillez avec Segue. Vous pouvez l'exclure du code et appeler performSegue (withIdentifier: sender :) dans la méthode Router . La préparation n'est nécessaire que si vous devez utiliser Segue avec le transfert de données.|  | 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) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // ... | 
|  | } | 
Maintenant, nous arrivons enfin à la chose la plus intéressante - le code du 
routeur . L'exemple contient des commentaires, nous ne considérerons donc que les points clés.
Dans ce 
routeur, nous travaillons avec deux scènes - 
Home et 
Detail . La transition de la scène d' 
accueil est également gérée de deux manières - par 
Segue et par 
programme . Les données sont transférées de la scène d' 
accueil à la scène de 
détail .
Toutes les méthodes du protocole 
RoutingLogic doivent être nommées selon le principe 
routeToNAME , où 
NAME est le nom du 
Segue (identifiant) que nous spécifions lorsque nous travaillons avec le 
Storyboard . Cela est nécessaire non seulement pour la commodité et la beauté de l'utilisation, mais aussi pour notre sélecteur de méthode dans 
prepare (pour: sender :) ViewController , que nous avons redéfini plus tôt.
Dans la classe 
HomeRouter , 
il existe également des méthodes commençant par 
naviguerTo et 
passDataTo . Les premiers sont responsables de la logique de transition, tandis que les seconds sont responsables du transfert des données. Les méthodes naviguer vers ne sont créées que si la transition est effectuée par programme.
Dans l'exemple, nous avons une 
méthode routeToDetail (segue :) . Le paramètre 
segue est facultatif car la méthode contient une implémentation qui vous permet de l'appeler sans utiliser 
Segue . Dans les deux cas de transition, nous obtenons des valeurs non facultatives de notre scène 
HomeViewController et 
HomeDataStore'a Home , ainsi que des liens vers la scène 
ViewController et 
DataStore Detail . Ici, il convient de prêter attention au fait que 
detailDS est une variable et est passée à la méthode 
passDataToDetail en utilisant le paramètre 
pass -through (inout). Ceci est important car sans 
inout, nous devrons marquer tous les protocoles 
DataStore comme «possible à implémenter uniquement avec des classes» (protocole DetailDataStore: classe), ce qui entraîne de nombreuses difficultés, notamment la capture de liens forts.
|  |  | 
|  | 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 | 
|  | } | 
|  | } | 
Conclusion
C’est tout. Merci d'avoir lu jusqu'au bout! Ci-dessous, je laisserai un lien vers le projet si vous souhaitez essayer l'article en action.
Série d'articles
- Présentation de Clean Swift Architecture
- Routeur et passage de données dans une architecture Clean Swift (vous êtes ici)
- Travailleurs de l'architecture propre et rapide
- Tests unitaires dans l'architecture Clean Swift
- Un exemple d'une architecture de boutique en ligne simple Clean Swift
Lien vers le projetAide à la rédaction d'un article: 
Bastien