Halo pembaca!
Dalam artikel 
sebelumnya , saya berbicara tentang siklus 
VIP arsitektur 
Clean Swift . Sekarang kita akan menyentuh salah satu topik paling penting - 
transisi dan 
transfer data antar adegan.

Teori
Komponen 
Router bertanggung jawab atas navigasi dan transfer data, yang merupakan bagian dari adegan (opsional tentu saja). Ini diinisialisasi dalam 
ViewController , bersama dengan 
Interactor dan 
Presenter .
Router mengimplementasikan dua protokol - 
RoutingLogic dan 
DataPassing , yang akan kami isi dengan fungsionalitas kami. 
RoutingLogic harus berisi metode yang bertanggung jawab untuk transisi ke adegan tertentu. 
DataPassing berisi variabel 
dataStore , yang merujuk pada Protokol 
DataStore . Adegan 
Interactor mengimplementasikan protokol 
DataStore dan bekerja dengan variabel yang disimpan di dalamnya. 
Router itu sendiri berisi tautan ke 
ViewController dari adegannya.
Menggunakan tautan ke 
ViewController , 
Router melompat di antara layar. Untuk melakukan ini, Anda dapat menggunakan 
Segue atau membuat adegan yang ingin Anda transisikan, secara terprogram. Metode mana yang digunakan tidak penting, hal utama bagi kita adalah memiliki tautan ke turunan kelas 
ViewController yang akan kita gunakan.
Dengan menggunakan tautan ke 
DataStore, kami akan mentransfer data dari 
Interactor dari satu adegan ke 
Interactor dari adegan yang kami pindahkan. Dan, seperti yang disebutkan sebelumnya, 
Routerlah yang perlu tahu bagaimana melakukan ini.
Berlatih
Sebagai contoh, kami akan mentransfer teks dari TextField ke Label adegan lain. Mari kita pertimbangkan dua cara transisi antar adegan - menurut 
Segue dan secara terprogram.
Kelas 
Router berisi 3 kelompok metode semantik:
- Metode dari implementasi RoutingLogic (routeTo)
- Metode yang bertanggung jawab untuk navigasi (navigasikan ke, transisi tanpa Segue)
- Metode untuk transfer data (passDataTo, jika ada data untuk transfer)

Jika kita melakukan transisi melalui 
Segue , misalnya, ketika sebuah tombol diklik, maka di 
ViewController kita harus mengganti metode prep (for: sender :). Ekstensi ini akan memungkinkan Anda untuk secara otomatis memanggil metode dari 
Router dengan nama 
Segue .
Mempersiapkan persiapan (untuk: pengirim :) adalah opsional ketika bekerja dengan Segue. Anda dapat mengecualikannya dari kode dan memanggil performSegue (withIdentifier: sender :) dalam metode Router . Mempersiapkan hanya diperlukan jika Anda perlu menggunakan Segue bersama dengan transfer data.|  | 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) | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // ... | 
|  | } | 
Sekarang akhirnya kita sampai pada hal yang paling menarik - kode 
Router . Contoh tersebut berisi komentar, jadi kami hanya akan mempertimbangkan poin-poin penting.
Di 
Router ini 
, kami bekerja dengan dua adegan - 
Beranda dan 
Detail . Transisi dari adegan 
Home juga ditangani dalam dua cara - oleh 
Segue dan secara 
terprogram . Data ditransfer dari adegan 
Beranda ke adegan 
Detail .
Semua metode dalam protokol 
RoutingLogic harus dinamai sesuai dengan prinsip 
routeToNAME , di mana 
NAME adalah nama 
Segue (Identifier) โโyang kami tentukan saat bekerja dengan 
Storyboard . Ini diperlukan tidak hanya untuk kenyamanan dan keindahan penggunaan, tetapi juga untuk pemilih metode kami dalam 
persiapan (untuk: pengirim :) ViewController , yang telah kami definisikan ulang sebelumnya.
Juga di kelas 
HomeRouter ada metode yang dimulai dengan 
navigTo dan 
passDataTo . Yang pertama bertanggung jawab untuk logika transisi, sedangkan yang kedua bertanggung jawab untuk transfer data. Metode navigo hanya dibuat jika transisi dilakukan secara terprogram.
Pada contoh, kita memiliki metode 
routeToDetail (segue :) . Parameter 
segue bersifat opsional sejak itu metode ini berisi implementasi yang memungkinkan Anda untuk memanggilnya tanpa menggunakan 
Segue . Dalam kedua kasus transisi, kita mendapatkan nilai-nilai non-opsional dari 
adegan HomeViewController'a dan 
HomeDataStore'a kami, serta tautan ke adegan 
ViewController dan 
DataStore Detail . Di sini perlu diperhatikan fakta bahwa 
detailDS adalah variabel dan diteruskan ke metode 
passDataToDetail menggunakan parameter 
pass -through (inout). Ini penting karena tanpa 
inout, kita harus menandai semua protokol 
DataStore sebagai "mungkin untuk diimplementasikan hanya dengan kelas" (protokol DetailDataStore: class), dan ini memerlukan banyak kesulitan, termasuk menangkap tautan yang kuat.
|  |  | 
|  | 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 | 
|  | } | 
|  | } | 
Kesimpulan
Itu saja. Terima kasih sudah membaca sampai akhir! Di bawah ini saya akan meninggalkan tautan ke proyek jika Anda ingin mencoba artikel tersebut dalam tindakan.
Seri artikel
- Tinjauan Arsitektur Swift Bersih
- Router dan Passing Data dalam arsitektur Swift Bersih (Anda di sini)
- Pekerja Arsitektur Swift Bersih
- Pengujian unit dalam arsitektur Clean Swift
- Contoh arsitektur toko online sederhana Clean Swift
Tautan ke proyekBantuan dalam menulis artikel: 
Bastien