Menulis Aplikasi iOS Menggunakan Pola Redux

gambar

Baru-baru ini, saya lebih terlibat dalam pengembangan front-end daripada mobile, dan saya menemukan beberapa pola desain yang sangat menarik yang sudah saya ketahui, tetapi tidak benar-benar membahasnya ... sampai sekarang.

Tapi sekarang semua ini masuk akal, setelah menggunakan dari pengembangan React selama beberapa minggu, sekarang saya tidak bisa kembali ke cara lama saya mengembangkan untuk iOS. Saya tidak akan beralih ke javascript (AKA React Native) untuk mengembangkan aplikasi seluler, tetapi di sini ada beberapa hal yang saya pelajari.

gambar

Kembali ke pengembangan iOS, saya membuat proyek baru dan mulai menjelajahi ReSwift , ini merupakan implementasi dari pola Flux dan Redux di Swift. Dan itu bekerja cukup sederhana, saya mengkloning arsitektur aplikasi JavaScript beberapa kali, sekarang saya memiliki keadaan global, dan pengendali saya hanya mendengarkan keadaan ini. Kontroler itu sendiri terdiri dari berbagai komponen presentasi yang merangkum perilaku yang sangat spesifik.

gambar

Semua perubahan status dilakukan di satu tempat, dalam peredam . Satu untuk media. Anda dapat melihat semua tindakan di satu tempat. Tidak ada lagi kode jaringan atau pengendali panggilan, tidak ada lagi mutasi objek dalam tampilan. Tidak ada lagi kode spageti. Hanya ada satu negara , dan itu benar, maka berbagai komponen presentasi Anda (dan saya bersikeras) berlangganan ke berbagai bagian negara dan bereaksi sesuai. Ini hanyalah arsitektur terbaik untuk aplikasi model yang kuat.

Sebagai contoh. Sebelumnya, pengendali tampilan login dipenuhi dengan banyak baris kode, berbagai status kontrol, penanganan kesalahan, dll ... Sekarang terlihat seperti ini: (Sebagai contoh)

import UIKit import Base import ReSwift class LoginViewController: UIViewController { @IBOutlet var usernameField: UITextField! @IBOutlet var passwordField: UITextField! override func viewDidLoad() { super.viewDidLoad() store.subscribe(self) {state in state.usersState } } @IBAction func onLoginButton(_ sender: Any) { store.dispatch(AuthenticatePassword(username: usernameField.text!, password: passwordField.text!)) } @IBAction func onTwitterButton(_ sender: Any) { store.dispatch(AuthenticateTwitter()) } @IBAction func onFacebookButton(_ sender: Any) { store.dispatch(AuthenticateFacebook(from: self)) } } // MARK: - State management extension LoginViewController: StoreSubscriber { func newState(state: UsersState) { if let error = state.authState.error { presentError(error: error.type, viewController: self, completion: nil) } if let _ = state.getCurrentUser { self.dismiss(animated: true, completion: nil) } } } 

Pengendali dan representasi tindakan pengiriman di negara global, tindakan ini sebenarnya bekerja dengan jaringan atau meluncurkan berbagai bagian yang perlu dikonversi oleh aplikasi Anda ke negara baru.

Suatu tindakan dapat memicu tindakan lain, ini adalah bagaimana hal itu terjadi untuk permintaan jaringan, misalnya, Anda memiliki satu tindakan FetchUser (id: String) dan satu tindakan yang Anda intersep dalam peredam yang terlihat seperti SetUser (pengguna: Pengguna). Dalam peredam, Anda bertanggung jawab untuk menggabungkan / menggabungkan objek baru dengan kondisi Anda saat ini.

Pertama Anda membutuhkan status , contoh saya akan fokus di sekitar objek Pengguna , jadi status mungkin terlihat seperti ini:

 struct UsersState { var users: [String: User] = [:] } 

Anda harus memiliki file yang merangkum semua aktivitas jaringan untuk objek pengguna.

 struct FetchUser: Action { init(user: String) { GETRequest(path: "users/\(user)").run { (response: APIResponse<UserJSON>) in store.dispatch(SetUser(user: response.object)) } } } 

Segera setelah permintaan selesai, ia memanggil tindakan lain, tindakan ini sebenarnya kosong, harus dirujuk, misalnya, di UsersActions. Tindakan ini menjelaskan hasil yang harus diandalkan peredam untuk mengubah status.

 struct SetUser: Action { let user: UserJSON? } 

Dan akhirnya, pekerjaan yang paling penting dilakukan di UsersReducer , Anda perlu menangkap tindakan dan melakukan beberapa pekerjaan sesuai dengan isinya:

 func usersReducer(state: UsersState?, action: Action) -> UsersState { var state = state ?? initialUsersState() switch action { case let action as SetUser: if let user = action.user { state.users[user.id] = User(json: user) } default: break } return state } 

Sekarang semua yang diperlukan adalah suscribe / berlangganan negara dalam pengontrol atau tampilan, dan ketika itu berubah, ekstrak informasi yang diperlukan dan dapatkan nilai-nilai baru!

 class UserViewController: UIViewController { var userId: String? { didSet { if let id = userId { store.dispatch(FetchUser(user: id)) } } } var user: User? { didSet { if let user = user { setupViewUser(user: user) } } } override func viewDidLoad() { super.viewDidLoad() store.subscribe(self) {state in state.usersState } } func setupViewUser(user: User) { //Do uour UI stuff. } } extension UserViewController: StoreSubscriber { func newState(state: UsersState) { self.user = state.users[userId!] } } 

Tetapi sekarang Anda harus melihat contoh ReSwift untuk pemahaman yang lebih dalam, saya berencana untuk menerbitkan aplikasi open source (sebenarnya sebuah game) menggunakan pola desain ini. Tetapi untuk sekarang, kode ini menampilkan ide yang sangat kasar tentang bagaimana semua ini bekerja bersama.

Ini masih merupakan arsitektur yang sangat awal dalam buku Glose, tetapi kami tidak sabar menunggu aplikasi untuk diproduksi menggunakan arsitektur ini.

Saya merasa bahwa mengembangkan aplikasi menggunakan pola ini akan menghemat banyak waktu dan tenaga. Dibutuhkan lebih banyak pekerjaan daripada klien REST yang bodoh dan sederhana, karena akan ada sedikit lebih banyak logika di dalam status klien, tetapi pada akhirnya itu akan menghemat waktu Anda yang tak ternilai untuk debugging. Anda akan dapat memodifikasi banyak elemen secara lokal, dan tidak akan ada lagi perubahan cascading antara pengontrol dan tampilan. Mereproduksi keadaan dalam urutan cadangan, mengarsipnya, membuat middleware, dll. Aliran data aplikasi jelas, terpusat, dan sederhana.

Pola Redux menambahkan sedikit struktur ke aplikasi. Saya telah melakukan MVC murni untuk waktu yang sangat lama, saya yakin Anda dapat membuat basis kode yang bersih, tetapi Anda cenderung mengembangkan kebiasaan yang sering kali lebih berbahaya daripada baik. Anda bahkan dapat mengambil langkah lebih jauh dan sepenuhnya mengimplementasikan Redux dengan mengendalikan antarmuka pengguna Anda (seperti pengontrol tampilan, pengamat peringatan, pengontrol perutean) dalam keadaan terpisah, tapi saya belum mencapai semua ini).

Dan pengujiannya ... Pengujian unit sekarang mudah diimplementasikan, karena yang perlu Anda uji adalah membandingkan data yang Anda masukkan dengan data yang terkandung dalam keadaan global, sehingga tes dapat mengirim tindakan tiruan, dan kemudian memeriksa apakah negara cocok dengan apa yang Anda mau.

Serius, ini masa depan. Masa depan adalah untuk Redux :)

Source: https://habr.com/ru/post/id464561/


All Articles