Saya mencoba melakukan arsitektur untuk aplikasi SwiftUI yang lebih besar dan siap produksi. Saya menjalankan semua waktu ke masalah yang sama yang menunjuk ke cacat desain utama di SwiftUI.
Masih tidak ada yang bisa memberi saya jawaban yang berfungsi penuh, siap produksi.
Bagaimana cara melakukan Tampilan yang dapat digunakan kembali SwiftUI
yang mengandung navigasi?
Karena SwiftUI
NavigationLink
sangat terikat pada tampilan ini tidak mungkin sedemikian rupa sehingga skala juga dalam Aplikasi yang lebih besar. NavigationLink
dalam contoh kecil Aplikasi itu berfungsi, ya - tetapi tidak segera setelah Anda ingin menggunakan kembali banyak Tampilan dalam satu Aplikasi. Dan mungkin juga menggunakan kembali batas-batas modul. (seperti: menggunakan kembali Tampilan di iOS, WatchOS, dll ...)
Masalah desain: NavigationLinks di-hardcode ke dalam View.
NavigationLink(destination: MyCustomView(item: item))
Tetapi jika tampilan yang mengandung ini NavigationLink
harus dapat digunakan kembali saya tidak dapat membuat hardcode tujuan. Harus ada mekanisme yang menyediakan tujuan. Saya bertanya di sini dan mendapat jawaban yang cukup baik, tetapi masih belum jawaban lengkap:
SwiftUI MVVM Coordinator / Router / NavigationLink
Idenya adalah untuk menyuntikkan Tautan Tujuan ke tampilan yang dapat digunakan kembali. Secara umum ide ini bekerja tetapi sayangnya ini tidak skala ke Aplikasi Produksi nyata. Segera setelah saya memiliki beberapa layar yang dapat digunakan kembali, saya mengalami masalah logis bahwa satu tampilan yang dapat digunakan kembali ( ViewA
) membutuhkan tampilan-tujuan yang telah dikonfigurasikan sebelumnya ( ViewB
). Tetapi bagaimana jika ViewB
juga membutuhkan view-destination yang telah dikonfigurasi sebelumnya ViewC
? Saya akan perlu membuat ViewB
sudah sedemikian rupa sehingga ViewC
disuntikkan sudah di ViewB
sebelum saya menyuntikkan ViewB
ke dalam ViewA
. Dan seterusnya .... tetapi karena data yang pada saat itu harus dilewati tidak tersedia, keseluruhan konstruksinya gagal.
Gagasan lain yang saya miliki adalah menggunakan Environment
mekanisme injeksi ketergantungan untuk menyuntikkan tujuan NavigationLink
. Tapi saya pikir ini harus dianggap kurang lebih sebagai peretasan dan bukan solusi yang dapat diskalakan untuk Aplikasi besar. Kami pada akhirnya akan menggunakan Lingkungan pada dasarnya untuk semuanya. Tetapi karena Lingkungan juga dapat digunakan hanya di dalam View (tidak di Koordinator atau ViewModels terpisah) ini lagi akan membuat konstruksi aneh menurut saya.
Seperti logika bisnis (misalnya kode model tampilan) dan tampilan harus dipisahkan juga navigasi dan tampilan harus dipisahkan (misalnya pola Koordinator) Di UIKit
dalamnya dimungkinkan karena kami mengakses ke UIViewController
dan di UINavigationController
belakang tampilan. UIKit's
MVC sudah memiliki masalah yang membuat begitu banyak konsep sehingga menjadi nama yang menyenangkan "Massive-View-Controller" bukannya "Model-View-Controller". Sekarang masalah yang sama terus berlanjut SwiftUI
tetapi bahkan lebih buruk lagi menurut saya. Navigasi dan Tampilan sangat digabungkan dan tidak dapat dipisahkan. Karenanya tidak mungkin untuk melakukan tampilan yang dapat digunakan kembali jika mengandung navigasi. Itu mungkin untuk menyelesaikan ini, UIKit
tetapi sekarang saya tidak dapat melihat solusi yang masuk akalSwiftUI
. Sayangnya Apple tidak memberikan penjelasan kepada kami bagaimana menyelesaikan masalah arsitektur seperti itu. Kami hanya mendapat beberapa Aplikasi sampel kecil.
Saya ingin terbukti salah. Tolong tunjukkan saya pola desain App bersih yang memecahkan ini untuk Aplikasi siap produksi besar.
Terima kasih sebelumnya.
Pembaruan: karunia ini akan berakhir dalam beberapa menit dan sayangnya masih tidak ada yang bisa memberikan contoh yang berfungsi. Tetapi saya akan memulai karunia baru untuk menyelesaikan masalah ini jika saya tidak dapat menemukan solusi lain dan menautkannya di sini. Terima kasih untuk semua untuk Kontribusi mereka yang luar biasa!
Jawaban:
Penutupan adalah semua yang Anda butuhkan!
Saya menulis posting tentang mengganti pola delegasi di SwiftUI dengan penutupan. https://swiftwithmajid.com/2019/11/06/the-power-of-closures-in-swiftui/
sumber
Ide saya akan menjadi kombinasi
Coordinator
danDelegate
pola. Pertama, buatCoordinator
kelas:Adaptasi
SceneDelegate
untuk menggunakanCoordinator
:Di dalam
ContentView
, kami memiliki ini:Kita dapat mendefinisikan
ContenViewDelegate
protokol seperti ini:Di mana
Item
hanya sebuah struct yang dapat diidentifikasi, bisa berupa apa saja (misalnya id dari beberapa elemen seperti diTableView
dalam UIKit)Langkah selanjutnya adalah mengadopsi protokol ini
Coordinator
dan cukup menyampaikan pandangan yang ingin Anda sajikan:Sejauh ini ini berfungsi dengan baik di aplikasi saya. Saya harap ini membantu.
sumber
Text("Returned Destination1")
ke sesuatu sepertiMyCustomView(item: ItemType, destinationView: View)
. SehinggaMyCustomView
juga perlu beberapa data dan tujuan disuntikkan. Bagaimana Anda menyelesaikannya?dependencies
dandestination
.Text("Returned Destination1")
. Bagaimana jika ini perlu aMyCustomView(item: ItemType, destinationView: View)
. Apa yang akan Anda suntikkan di sana? Saya memahami injeksi dependensi, kopling longgar melalui protokol, dan dependensi bersama dengan koordinator. Semua itu bukan masalah - itu adalah sarang yang dibutuhkan. Terima kasih.Sesuatu yang terjadi pada saya adalah ketika Anda mengatakan:
itu tidak sepenuhnya benar. Daripada menyediakan tampilan, Anda dapat merancang komponen yang dapat digunakan kembali sehingga Anda memberikan penutupan yang memasok tampilan pada permintaan.
Dengan cara itu penutupan yang menghasilkan ViewB on demand dapat menyediakannya dengan penutupan yang menghasilkan ViewC on demand, tetapi konstruksi aktual dari pandangan dapat terjadi pada saat informasi kontekstual yang Anda butuhkan tersedia.
sumber
Ini adalah contoh menyenangkan dari menelusuri tanpa batas dan mengubah data Anda untuk tampilan detail selanjutnya secara terprogram
sumber
Saya sedang menulis seri posting blog tentang cara membuat pendekatan MVP + Coordinators di SwiftUI yang mungkin berguna:
https://lascorbe.com/posts/2020-04-27-MVPCoordinators-SwiftUI-part1/
Proyek lengkap tersedia di Github: https://github.com/Lascorbe/SwiftUI-MVP-Coordinator
Saya mencoba melakukannya seolah-olah itu akan menjadi aplikasi besar dalam hal skalabilitas. Saya pikir saya sudah menyelesaikan masalah navigasi, tapi saya masih harus melihat bagaimana melakukan deep linking, yang saat ini saya kerjakan. Saya harap ini membantu.
sumber
NavigationView
tampilan root sangat fantastis. Sejauh ini, ini adalah implementasi Koordinator SwiftUI paling canggih yang saya lihat sejauh ini.NavigationLink
tetapi melakukannya dengan memperkenalkan ketergantungan baru digabungkan. DalamMasterView
contoh Anda tidak bergantung padaNavigationButton
. Bayangkan menempatkanMasterView
dalam Paket Swift - itu tidak akan dikompilasi lagi karena jenisnyaNavigationButton
tidak diketahui. Juga saya tidak melihat bagaimana masalah reusable bersarangViews
akan diselesaikan olehnya?Ini adalah jawaban yang benar-benar luar biasa, jadi mungkin akan berubah menjadi omong kosong, tetapi saya akan tergoda untuk menggunakan pendekatan hybrid.
Gunakan lingkungan untuk melewati objek koordinator tunggal - sebut saja NavigationCoordinator.
Berikan pandangan yang dapat digunakan kembali Anda semacam pengidentifikasi yang diatur secara dinamis. Identifier ini memberikan informasi semantik yang sesuai dengan kasus penggunaan aktual dan hierarki navigasi aplikasi klien.
Mintalah pandangan yang dapat digunakan kembali meminta Navigator untuk tampilan tujuan, melewati pengidentifikasi mereka dan pengidentifikasi jenis tampilan yang mereka navigasikan.
Ini meninggalkan NavigationCoordinator sebagai titik injeksi tunggal, dan itu adalah objek non-view yang dapat diakses di luar hierarki tampilan.
Selama penyetelan, Anda dapat mendaftarkan kelas tampilan kanan agar kembali, menggunakan semacam pencocokan dengan pengidentifikasi yang diteruskan saat runtime. Sesuatu yang sederhana seperti mencocokkan dengan pengidentifikasi tujuan mungkin berfungsi dalam beberapa kasus. Atau cocok dengan sepasang pengidentifikasi host dan tujuan.
Dalam kasus yang lebih kompleks, Anda dapat menulis pengontrol khusus yang memperhitungkan informasi spesifik aplikasi lainnya.
Karena itu disuntikkan melalui lingkungan, tampilan apa pun dapat mengesampingkan NavigationCoordinator default di setiap titik dan menyediakan yang berbeda untuk subview-nya.
sumber