The original translation
-
Khanlou.com/2015/01/the…
-
Khanlou.com/2015/10/coo…
-
Khanlou.com/tag/advance…
-
www.hackingwithswift.com/articles/71…
-
medium.com/@saad.eloul…
-
Aplus. Rs / 2018 / coordi…
The Coordinator design pattern in iOS was first proposed by Soroush Khanlou in 2015. It fully implements object-oriented principles and is another successful application of OOP and POP in the iOS space. However, as far as I know, this mode is seldom discussed and practiced in China, and more heavyweight methods similar to UrlRouter are used. This time, I would like to translate some classic articles about Coordinators to give an overview, hoping to inspire readers.
One of the biggest problems with view controllers is that they mix your navigation logic, view logic, and business logic.
When a tableViewCell is selected, the proxy method usually looks like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
id object = [self.dataSource objectAtIndexPath:indexPath];
SKDetailViewController *detailViewController = [[SKDetailViewController alloc] initWithDetailObject:object]
[self.navigationController presentViewController:detailViewController animated:YES];
}
Copy the code
Three simple lines of code do three things: get the model object, create the view controller, and show the view controller. In a fairly simple App, this is no problem at all. Each view controller will most likely only be used once. Coupling them like this is not a dangerous operation. However, as your App gets more complex, a controller may be used in a new place. Maybe it will be adapted to the iPad, maybe it will be in APP Extension, maybe it will be a new logic for an old business.
If the navigation logic is written in a view controller, the controller cannot reuse its existing view display logic without dragging and dropping all the code. Don’t forget that the base class of a view controller is prefixed with UI, which means it is a view object and is out of its depth to handle user logic.
In the code above, the view controller knows how to create the next object in the entire business flow and how to display it. In the third line of code, it tells its superview controller what to do, which clearly reverses black and white. To make matters worse, similar code is spread across multiple view controllers, each of which only knows how to do the next step.
I used to think that view controller was the top thing in the App, the thing that knew how to run the whole process. Recently, however, I have found that having a view controller directed by a higher-level object whose role is to lead and manage all view controllers within its jurisdiction has many advantages.
I call these people Coordinators, or I can call them Directors. To really perform this pattern well, you need a high-level coordinator to guide the entire application (sometimes called the application Controller pattern). An AppDelegate holds an AppCoordinator, and each coordinator has a set of child coordinators. Especially if you have more than one controller, as in the TAB bar application, each navigation controller has its own coordinator to guide its behavior and navigation flow. You can create more child coordinators for specific tasks such as registering or creating content. Each coordinator is created by its parent coordinator. Using this pattern early in the development process is useful even for single-step tasks such as authentication.
The coordinator is a PONSO(Plain Old NSObjects) pure NSObject object. For the Instagram photo creation process, we can use the PhotoCreationCoordinator. The APP coordinator can generate a new view and pass the root view controller to it so that it can render the first view controller in the flow.
- (void)beginPhotoCreationProcess {
PhotoCreationCoordinator *coordinator = [[PhotoCreationCoordinator alloc] initWithRootViewController:self.rootViewController delegate:self]
[self.childCoordinators addObject:coordinator];
[coordinator beginPhotoCreationProcess];
}
- (void)photoCreationCompletedSuccessfully:(PhotoCreationCoordinator *)coordinator {
[self.childCoordinators removeObject:coordinator];
}
- (void)photoCreationCanceled:(PhotoCreationCoordinator *)coordinator {
[self.childCoordinators removeObject:coordinator];
}
Copy the code
Coordinator – beginPhotoCreationProcess method can now create a new image selection view controller, and according to the need to configure it. The coordinator can become a delegate to the photo selection view controller so that it can be notified when the next step is displayed. No view controller in the process needs to know about any other view controllers. Every view controller is an island.
Business logic (such as publishing photos) is wrapped in its own objects and can be moved up to the coordinator or down to the model as needed. Either way, it’s moved out of the view controller. Moving it to the coordinator is great because the coordinator already acts as the glue between different parts of the code.
There are numerous benefits to extracting flows into the coordinator. The view controller can now focus on binding the model to the view. They can be reused more easily, for example in extended or unbound applications, without the need for complex conditions to manage different contexts. A/B testing is as simple as creating A different coordinator object and using it to start the process. Navigation logic now has a home, and it feels really good to have a home.
Initialization of the view controller is also extracted. This cannot be ignored. Initialization is always a seemingly simple but actually more complex task that requires a lot of knowledge about classes and configuration, and we move it to a better place where more informed decisions can be made.
The coordinator object unconsciously holds many separate states; in other words, especially for iPhone applications, only one screen is visible at any one time. This makes them a natural place to use state machines to manage all their data. The best implementation of a state machine is a one-way data stream.
Apple likes to make the view controller the center of the iOS world. This is evident in iOS 8’s new UISplitViewController API and Interface Builder components like Storyboard segues. Unfortunately, the view controller-centric approach to application development is not scalable. Coordinators are a great way to isolate code into small, easily replaceable chunks that can be part of the solution to view controller problems.