-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MVVM - Navigation Analysis #23
Comments
IntroductionThere are two main approaches for navigating between controllers. Coordinator and flow coordinators. Both of them have very abstract definitions therefore have very different implementations. Rather than explaining the abstract definitions of these patterns, I will share some basic implementations of these patterns just to give an idea of what they look like. Coordinatorprotocol Coordinator {
var childCoordinators: [Coordinator] { get set }
var navigationController: UINavigationController { get set }
func start()
} class FirstCoordinator: Coordinator {
//Used for holding sub-coordinators
var childCoordinators = [Coordinator]()
var navigationController: UINavigationController
init(navigationController: UINavigationController) {
self.navigationController = navigationController
}
func start() {
let controller = FirstViewController()
controller.coordinator = self
navigationController.pushViewController(controller, animated: false)
}
func route(with data: String) {
let vc = SecondViewController()
navigationController.pushViewController(vc, animated: false)
}
} class FirstViewController: UIViewController {
weak var coordinator: FirstCoordinator?
@IBAction func route(_ sender: Any) {
coordinator?.route(with: "Data")
}
} Flow CoordinatorFlowCoordinator is basically the same pattern with the Coordinator expect for the one fact that the Coordinator itself is basically a UIViewController rather than some abstract Protocol. class FirstFlowController: UIViewController {
private let navigation = UINavigationController()
override func viewDidLoad() {
super.viewDidLoad()
let firstViewController = FirstViewController()
firstViewController.delegate = self
navigation.show(firstViewController, sender: self)
add(navigation)
}
func add(_ child: UIViewController) {
addChild(child)
view.addSubview(child.view)
child.didMove(toParent: self)
}
}
protocol FlowControllerDelegate {
func route(with data: String)
}
extension FirstFlowController: FlowControllerDelegate {
func route(with data: String) {
let vc = SecondViewController()
navigationController.pushViewController(vc, animated: false)
}
} class FirstViewController: UIViewController {
weak var delegate: FlowControllerDelegate?
@IBAction func route(_ sender: Any) {
delegate?.route(with: "Data")
}
} There are few differences between these patterns but the one I found most important is syncing sub-coordinators with UINavigationController. Users can tap on the back button in UINavigationViewController and this would pop the current view controller out of the navigation stack but then we would need to tell our Parent-Coordinator somehow to remove child-coordinator from stack too. (see here) There is a more detailed comparison of these two here. |
Coordinator pattern will be used for navigation. |
Navigation approaches and patterns in MVVM should be analyzed.
The text was updated successfully, but these errors were encountered: