That’s a recent question from the comments put in my own words. A view model that encapsulates the display state sounds promising at first. But when you don’t have a simple view that displays one thing, how do you model that in code? How do you model a sequence of view controllers, for example a more complex checkout process?
Krzysztof Zabłocki (@merowing_) shared his approach to “Behaviors” in a Slack channel the other day. These are functional extensions to view controllers that you can wire via Interface Builder (!) to inject behavior into a scene.
In a top secret project I am working on, I think I found a consistent way to create UITableViewControllers in a reusable fashion without making a mess with massive view controllers. The key ingredient is, as always, delegation from the view controller and thus composing larger components:
View Controllers should only be responsible for view lifecycle events, Marcus Zarra reminds us. That means they should populate views with data, and show and hide them – stuff like that. View controllers should not do the work of views.
While I like his overall advice, it contains a few problematic points:
Put Core Data out of the view controller. His solution to provide a single data source tied to a NSManagedObjectContext will not scale well as I’ve experienced. – Still, don’t tie it to the view controllers. That makes matters worse.
His definition of “business logic” is odd. Business logic is not reducible to I/O code. It’s not just about fetching data from a device and doing network requests – except when your app is a very, very simplistic display for data with CRUD operations. Business logic can exceed data-centric rules and entail a real domain with complex behavior without much imagination.
Views should be responsible for displaying data, agreed. Since validation problems will be presented to the user, validation error messages will be part of that data, too. But views should not validate. Validation rule objects (WWDC’14 talk) should be the strategies that do validation.
If we create an object to sit between the view and the view controller then we are creating unnecessary additional objects.
Where do presenters sit? Between view and and view controller – but they make it easier to read and extend the code. They’re hardly unnecessary.
I strongly believe that it’s impossible to give advice about how to code and architect something if the problem domain isn’t part of the example. Because everything depends on the problem space in the end.
Remember to take every advice with a grain of salt. Collect things like Marcus’ tips to obtain new tools, but don’t take the tool for the solution of modelling a program to solve real problems.
There’s a WWDC 2014 talk called “Advanced iOS Application Architecture and Patterns”. In the first 30 minutes, you can learn a lot about designing information flow in your app. Sticking to Andy Matuschak’s example, a view controller is usually the place to put all behavior. (Hint: this is a bad idea.)
I’m writing unit tests for my Storyboard-based view controllers. Button interaction can be tested in view automation tests, but that’s slow, and it’s complicated, and it’s not even necessary for most cases. To write unit tests instead of UIAutomation tests for buttons, you test multiple things. Here are the tests.
Kevin McNeish created a Swift extension for UITextView to show a placeholder text when a text field is still empty. It takes all the burden from the view controller and is a real plug-in: it won’t interfere with existing code and only requires you add the file to your project. That’s it.