Closed blyscuit closed 4 months ago
In UIKit:
Pushing or popping two or more screens at once. => I can modify UINavigationController's viewControllers array to push multi screens, and then setViewControllers( :, animated:). To pop i can use popToViewController(; animated) to pop multiple screens at once.
Pushing that is not pre-set and determined by API response. => Easy to do in UIKit with imperative style.
Multiple entries to a particular screens. =>
To be reusable we can implement a Factory pattern so when we push/modal a new UIViewController we can use that Factory to init and setup data for new UIViewController before pushing. In my current project i apply a new pattern like this:
protocol BindableType: AnyObject {
associatedtype ViewModelType
var viewModel: ViewModelType! { get set }
func bindViewModel()
}
extension BindableType where Self: UIViewController {
func bindViewModel(to model: Self.ViewModelType, nibLoaded: Bool = false) {
viewModel = model
if !nibLoaded {
loadViewIfNeeded()
}
bindViewModel()
}
}
extension BindableType where Self: UIView {
func bindViewModel(to model: Self.ViewModelType) {
viewModel = model
bindViewModel()
}
}
import Foundation
struct Treatments: Flow {
let scene: Scene
init(scene: TreatmentsScene) {
self.scene = scene
}
}
enum TreatmentsScene: Scene {
case treatmentPlanDetails(TreatmentPlanDetailsViewModel)
case treatmentPeriodDetails(TreatmentPeriodDetailsViewModel)
case recommendationDetails(RecommendationDetailsViewModel)
}
extension TreatmentsScene {
func viewController() -> UIViewController {
switch self {
case let .treatmentPlanDetails(viewModel):
let vc = TreatmentPlanDetailsViewController()
vc.bindViewModel(to: viewModel)
return vc
case let .treatmentPeriodDetails(viewModel):
let vc = TreatmentPeriodDetailsViewController()
vc.bindViewModel(to: viewModel)
return vc
case let .recommendationDetails(viewModel):
let vc = RecommendationDetailsViewController()
vc.bindViewModel(to: viewModel)
return vc
}
}
}
and then push/modal new screen like this:
let sceneCoordinator = SceneCoordinator(navigationController: navigationController)
let vm = ViewModel()
sceneCoordinator.transitionTo(flow: Treatments(scene: .treatmentPlanDetails(vm)),
type: .push(hidesBottomBarWhenPushed: true))
contains UINavigationController.
In SwiftUI: To be honest, I haven't studied SwiftUI very deeply, so I'll answer these parts based on my limited knowledge. I will try to update in the near future :)
.navigationDestination(for:
Issue
How would you design an application with more complex navigation?
Examples: