Last active
July 10, 2022 14:32
-
-
Save AliSoftware/6d2d146f7baccb0099cc to your computer and use it in GitHub Desktop.
Coordinators & StateMachine - Concept
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct Coordinator { | |
let window: UIWindow | |
let navCtrl: UINavigationController? | |
func start() { | |
presentWelcomeScreen() | |
} | |
private func presentWelcomeScreen() { | |
let vc = WelcomeScreenViewController() // Instanciate from code, XIB, Storyboard, whatever your jam is | |
vc.navTransitions = WelcomeScreenTransitions( | |
showHome: self.pushHomeScreen, // see private func below | |
showCreateAccountScreen: self.pushCreateAccountScreen | |
) | |
window.rootViewController = vc // or whatever | |
} | |
private func pushHomeScreen(user: User?) { | |
let vc = HomeScreenViewController() // Instanciate from code, XIB, Storyboard, whatever your jam is | |
vc.user = user // or inject a ViewModel here if you're doing MVVM, you get the idea | |
vc.navTransitions = HomeScreenTransitions( | |
showUserInfoScreen: { | |
// From Home, we *push* the UserInfoVC | |
self.navigationController.pushViewController(instanciateUserInfoScreen(user), animated: true, completion: nil) | |
} | |
showProductDetail: self.pushProductDetail // extracted in private function below | |
disconnectAndShowLoginScreen: self.presentLoginScreen // same | |
) | |
navCtrl = UINavigationController(rootViewController: vc) | |
window.rootViewController = navCtrl | |
} | |
private func pushProductDetail(product: Product) { | |
let vc = ProductDetailViewController() // Instanciate from code, XIB, Storyboard, whatever your jam is | |
vc.product = product // inject any object to the VC, like a ViewModel or whatever | |
vc.navTransitions = ProductDetailTransitions( | |
showUserInfoScreen: { | |
// But from ProductDetail VC, we *present* the UserInfoVC *modally* | |
self.presentViewController(instanciateUserInfoScreen(product.owner), animated: true, completion: nil) | |
} | |
back: { navCtrl?.popViewController(animated: true) } | |
) | |
navCtrl?.pushViewController(vc, animated: true) { _ in } | |
} | |
private func pushCreateAccountScreen() { | |
// Create and push a CreateAccountViewController and its CreateAccountTransitions struct | |
... | |
} | |
private func instanciateUserInfoScreen(user: User) -> UIViewController { | |
// Create, configure and return an UserDetailsViewController | |
... | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct HomeScreenTransitions { | |
let showUserInfoScreen: Void -> Void | |
let showProductDetail: Product -> Void | |
let disconnectAndShowLoginScreen: Void -> Void | |
} | |
class HomeScreenViewController: UIViewController { | |
var navTransitions: HomeScreenTransitions! | |
@IBAction func profileAction(_: AnyObject) { | |
navTransitions.showUserInfoScreen() | |
} | |
@IBAction func disconnectAction(_: AnyObject) { | |
confirm("Are you sure?") { | |
navTransitions.disconnectAndShowLoginScreen() | |
} | |
} | |
@objc func tableView(tableView: UITableView, didSelectRowAtIndexPath: NSIndexPath) { | |
let product = productsDataSource[indexPath.row] | |
navTransitions.showProductDetail(product) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct Product { | |
let id: Int | |
let owner: User | |
... | |
} | |
struct ProductDetailTransitions { | |
let showUserInfoScreen: Void -> Void | |
let back: Void -> Void | |
} | |
class ProductDetailViewController: UIViewController { | |
var navTransitions: ProductDetailTransitions! | |
@IBAction func showProductOwner(_: AnyObject) { | |
navTransitions.showUserInfoScreen() | |
} | |
... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct WelcomeScreenTransitions { | |
let showHome: User? -> Void | |
let showCreateAccountScreen: Void -> Void | |
} | |
class WelcomeScreenViewController: UIViewController { | |
var navTransitions: WelcomeScreenTransitions! | |
var webService: WebServiceAPI! | |
@IBAction func loginAction(_: AnyObject) { | |
webService.login(userTextField.text, passwordTextField.text) { (user: User?) in | |
navTransitions.showHome(user) | |
} | |
} | |
@IBAction func createAccountAction(_: AnyObject) { | |
navTransitions.showCreateAccountScreen() | |
} | |
} |
How to do you handle the cas with UITabBarController with severals UIViewController ?
- create and instance the UITabBarController directly in the appCoordinator.
- group all the transitions in the UITabBarController
@remirobert good question never had that use case until know. Since that gist using closure I've finally switched back to the delegates version of that Coordinator pattern anyway, which avoids the risk of hidden retain cycles we have with closures everywhere here
@remirobert @AliSoftware any word or example code on using uitabcontroller with coordinator pattern?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
that's really awesome ! Good job AliSoftware 👽 .