MVC - the typical architectural pattern for many web languages, Objective-C and Swift included. Separation of concerns exist nicely in this pattern - the most immediate problem we have is that Cocoa Touch has bundled our V and C together into a ViewController. Thus, we have view logic and "glue" logic all in one place. Any idea what this may lead to...? That's right! We end up creating a different type of MVC - a massive view controller!
Our views and controllers end up very tightly coupled, and a ton of logic is thrown into our VCs because we can't think of any other good place to put it. MVVM - Model, View, ViewModel, attempts to alleviate this by having a ViewModel act as the new "controller". This lets the ViewController class created by Apple to be JUST a view - no controller logic there. The controller is then truly factored out and acts as a link between the view (which is represented by a ViewController subclass) and our model. This architectural pattern relies on data binding between the view and the ViewModel - that is, when a change is triggered in the ViewModel (based on a change in the model), the changes should cascade down to the view through data binding - KVO, anyone?
This isn't really all that different from TRUE mvc - this is a problem, as far as I'm concerned. All we've done is create a new repository to dump things that we don't know where else to put - instead of putting this logic in a VC alongside view code, we lump it into the viewModel. Yeah, our ViewController classes have less code now and are more focused and testable, but instead of having bloated ViewControllers, we have bloated ViewModels. THIS IS NOT A COMPELLING REASON TO CHANGE ARCHITECTURE PATTERNS - the two good things I can say about MVVM are that 1. You own your ViewModel, whereas you were previously putting a lot of logic into a ViewController (which is created by Apple and not you) and 2. ViewControllers are more testable with this approach.
What, then, can we do to truly improve our architecture? For one, create as many classes as you need to make sure that each file has single (or minimal) responsibility. Don't have a class called "BicycleVC" - instead, break that down into "BicyclePartsVC", "BicycleMaintenanceVC", etc. You don't even have to break it down into ViewControllers! Your files can just be regular objects that are used within another file, a controller somewhere else. By breaking down your files and naming them appropriately, all the while obsessively making sure that no class has too much responsibility, you greatly improve your architecture. No single class, not even a controller, will be saddled with too much responsibility and thus won't be saddled with too much code.
ANY OTHER DEVELOPER SHOULD BE ABLE TO LOOK AT YOUR CLASS NAMES AND, WITHOUT LOOKING AT THE SOURCE CODE, DETERMINE WHAT EACH CLASS DOES AND HOW THE "PIECES FIT TOGETHER".
Lots of data source code in a TableViewController subclass you're using? Factor it out. Lot's of networking code that encompasses multiple services being lobbed into your VC? Factor it out into several smaller classes, and, if it suits you, use a facade class to allow access to those (private, hopefully) internal APIs. When you think about it, a ViewModel is essentially a facade class used to access the model that is powering your software. Focus less on popular patterns and more on modularizing your classes, forcing minimal responsibility onto each class, and compulsively giving your files detailed names.