model should never talk with the view
, but so far I've always seen project that work in this way:
1- Controller
creates model object from database, stores it somewhere (array, dictionary, variables)
2- Controller
updates the view
accordingly, even using delegate methods f.i. in collectionViews.
My question is this: does the model need to represent perfectly what's going to be displayed by the view? So that I can pass the model object to the view and set the view according to it?
So far I've always implemented this procedure but I'd like to know if there's something wrong with this approach.
Example to be clear, in controller
:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! PostCollectionviewCell
cell.currentItem = self.posts[indexPath.item] as? Post
return cell
}
In view
using property observer
:
var currentItem :Post?{
didSet{
guard let thumbnailUrlString = self.currentItem?.thumbnailUrl else { return }
self.imageview.sd_setImage(with: URL(string: thumbnailUrlString))
bottomLayer.isHidden = true
}
}
You asked:
does the model need to represent perfectly what's going to be displayed by the view?
Yes, a model is, by definition, a representation of what is really going to be displayed.
So that I can pass the model object to the view and set the view according to it?
You can, but not necessarily do so. It's your call. This idea (of passing model object to view) is certainly a convenient pattern. For trivial apps, that’s fine.
The problem is that your views become entangled with the model. Instead, you might want to think of your view as something that is a little more abstract, designed, for example, to show lists of things that consist of an image and a text string. Then that view could be used for showing any list of things consisting of image and title.
At a minimum, you might define views to use protocols (e.g. a protocol for things that can be shown in a list), rather referring to concrete model types. Or give your cell a simple configure(image:text:)
method, and let the controller dictate what model properties are to be used.
Regardless, I would advise against storing a copy of a model object in a collection view cell. It only introduces confusion: If your UI allows you to edit the object, are you editing this copy in the cell, or the model? Theoretically, you can propagate changes with observers, but it can get confusing, and it is unnecessary here.
I get the impression that you might be thinking of the view controller as the MVC “controller”. Instead, many think of it more of part of the MVC “view”, as it fundamentally is all about preparing and populating views, reacting to user input, and responding to UI events. Many of us create more abstract “controllers” (or presenters or view models), something not tied to UIKit (or whatever). This also has the merit of letting us write unit tests for business logic, completely independent of the UI.
Here are a few links that rethink what MVC means and/or consider some logical alternatives:
See Dave Delong’s A Better MVC for a perspective of embracing MVC but employing techniques to keep them small and manageable.
See Medium’s iOS Architecture Patterns for a review of other approaches ranging from MVP, MVVM, Viper, etc.
See Krzysztof Zabłocki’s iOS Application Architecture for another good discussion on the topic.