Where to add persistent/networking code in a MVVM architecture - ios

I'm trying to make a project for learning purpose using MVVM. I get the idea on how this pattern works, but all of the examples I found are very basic and don't explain where exactly you add your persistent/networking code.
I am trying to use Core Data in my project.
Does someone has experience with this pattern ? I am reading that this kind of code should go in a NSOperation. Does this make sense ?
Any other thoughts ? I am just looking for some advice from other people who done this.
For now I am not interested in a Reactive approach.

Since asynchronous networking code can stay live well outside (and past) anything to do with the current UI, it should probably be put in a model object or other separate controller object, completely outside the view, view controller or view model hierarchy. Perhaps in a network controller object (custom class) attached at the app delegate level, so that networking state can be retained and gracefully shut down or handled in the background.

Related

Android call View Controller method from ViewModel

I started playing around with Android JetPack (ViewModel, Architecture Components, LIfeCycle and so on).
Untill now, I was working with Model View Presenter architecture, and actually I found it a quite easy to test and maintain architecture.
On the other hand, The big advantage I can see by using ViewModels instead, is their native coupling with Activities and Fragments lifecycle, which always was one of the biggest pains for Android developer, so I think this is a very big step forward.
Said that, I think there is a big disavantage though: with this new approach, it seems much more tricky to call Activity's or Fragment's methods, because, as stated in the official docs
A ViewModel must never reference a view, Lifecycle, or any class that
may hold a reference to the activity context.
In MVP approach, the Presenter had a contract with the view and could call all of its methods. I made some research on how to address this scenario with Architecture components, but it seem there is no easy and painless way to do that: at the end you always have to handle states in ViewModel and react to these changes in Activities and Fragments. Someone suggest to use SingleLiveEvent class, which makes it a little bit easier, but still much more painfull than before.
So my question is:
The docs say you cannot reference anything holding a reference to an Activity Context (to avoid memory leaks I guess), but what if I do that and then I clear all references in ViewModel's onCleared()?
You wouldn't avoid memory leaks, because for example if you rotate your device your activity will be destroyed, then recreated, but the VM would remain the same, and it's onCleared would not be called (hence your old activity still remains in memory, since your VM still references it).
Generally the MVVM conceptually says, that the ViewModels should not know about the View and this is the beauty of architecture: there is not a better pattern, just a more suitable one, and you should choose the one, that works better for you.
I can think of couple of ways to "notify a user" of the ViewModel:
A LiveData object that changes and an Observer to this data
Send a Broadcast to a BroadcastReceiver using the Application's Context, if you don't mind accessing it statically from the ViewModel
Edit: I know this is not exactly an answer to the question, but I think it removed the need for it
but what if I do that and then I clear all references in ViewModel's onCleared()?
That is far too late. onCleared() is only called if the Activity is finished / the Fragment is removed, it is not called on configuration changes.
But you could potentially use some form of command queue to emit events only when a subscriber is available, for example DispatchWorkSubject in RxJava2-Extensions.
Just make sure you make your subscriptions in onStart and then dispose your disposable in onStop.

MVVM in iOS: who is the responsible for the assembly?

I'm trying to apply MVVM architecture in my iOS project and I've read some articles like this one where it is said that:
(...) we can make the app-wide Router service which will be responsible for performing assembly and the View-to-View presentation
But I don't find any code sample for this kind of class, I'd really appreciate that somebody could explain the appropriate way to implement such "Router" class for a MVVM assembly, or say where I could find an example.
MVVM typically does not use a Router while Clean Architecture applications like VIPER or Clean Swift do.
In MVVMyou instantiate the root UIViewController in your AppDelegate, than set up the ViewModel and assign it to the view controllers viewModel property. Later on, one possible place to configure the upcomming MVVM scene in prepareForSegue.
This is a good explanation of MVVM, which also links to an example project.
You can certainly add those concepts to MVVM. If you want to do so, you can have a look in this Clean Swift example project, adapt the implementation concepts of Router and Configurator and develop your own, customized MVVM approach.
Your question(s) Who is responsible for setting up my MVVM scene and who is responsible for routing in-between scenes is very good though, as you are pinpointing one of the weaknesses of MVVM: Undefined responsibilities in this regards.
The second major weakness is bidirectional communication between ViewModel and View.
Bidirectional communication is also an issue in VIPER (View <-> Presenter and Presenter <-> Interactor).
The only iOS specific approach (I am aware of) which handles all of the mentioned issues is Clean Swift. I stop writing here as it gets off topic.

In which function to load tableView data when the data comes from remote API

I have a UITableViewController instance, which is the data source and the delegate.
The data is provided by a remote API, that takes some time to be called.
I know how to call and populate the cells for sure, but i don't know in which function i need to call the API that loads the data.
Typically i will have something like
var myData : [myOption]?
and when i populate the cells, i can ask if that array is nil or not and if not i can call the API, is this a good way?
Typically you're going to want to keep your data out of the view controller, and you absolutely want to keep your API calls out of the view controller. Create a "model" object that talks to the API. The simplest way to do this is to make the model a shared singleton. (There are some reasons not to use singletons here, but if you're new, I would absolutely do it this way.)
Again, to keep things simple, I recommend using NSNotification to let the model announce when data has changed. The view controller will observe this notification, and when it is posted, it'll call reloadData to refresh itself. All of the data source methods (numberOfRowsInSection, etc.) will be simple calls to the model.
This is the traditional way to build Cocoa apps, and the way I highly recommend people start. As you learn more, you'll probably find other tools that can be better than NSNotification, and you can learn other patterns that replace singletons. And you'll definitely learn better ways to update your table than reloadData, but this will get you a good, strong foundation to improve on.
One of the better pieces of example code, IMO, that demonstrates all of this is The Elements. I highly recommend studying it. It's in ObjC, but it's very clearly written, and learning to convert ObjC to Swift is a core competency of Cocoa developers. (The Elements doesn't talk to a server, but it demonstrates the Model View Controller pattern that you need.)

Model-Controller Abstraction with Core Data

In learning about Core Data, I've noticed how (in Xcode's templates) Apple directly used the query classes inside the view controller. This seems like it is bad MVC (having database access logic directly inside the view controller). Would it make sense to abstract out these kinds of actions to a separate suite of classes that obtain the data from the database and pass it back to the view controller calling it?
EDIT–
So, just to be clear, when I say "kinds of actions", I specifically mean CRUD Operations. Though if you have ideas about other things that a so-called "Model-Controller" would do, I'd be interested in hearing about them.
It's a matter of opinion, and often yes the templates are the most simple form of working example. It's hard to have a template spin out multiple files, for example.
Yes, personally, I generally spin out a separate NSManagedObject subclass. I like to have a _MySubclass object that has all the auto-generated stuff, then have the model actually reference MySubclass which has model-based business logic (you can use mogenerator or other methods to do this too if so inclined). Perhaps thinking of it as "Model-Controllers" and "View-Controllers" is another way of putting it.
This is a very good question and the answer likely depends on your situation. Perhaps architecture purists would insist on separate Model controllers and there are a lot of benefits to this approach. However, sometimes I find myself using Key Values when I'm doing a simple view. When things are more complex, for example, when coding the same Model for the Mac and iOS, having separate Model Controllers will allow you to reuse a lot of code. When you must diverge, Obj C Categories are a very clean way to extend functionality without adding a lot of overhead. I personally favor categories over extensive subclassing.
Since NSFetchedResultsController was released, my model classes are leaner. There are a lot of nuances to this and experience will help you come up with the best solution for your App. I've also found that writing unit tests up front will help you force through issues and validate your design, or send you back to the drawing board :)

Why does Apple documentation that getting ManagedObjectContext from UIApplicationDelegate is bad?

Just curious why ManagedObjectContexts should be passed to UIViewControllers when they are created, rather than just grabbing them from a UIApplicationDelegate?
The docs say that this makes your applications more rigid, but I am failing to see the nuances of when to use which pattern.
Thanks!
Imagine that I ask you to do some task, like painting a room. If I just tell you "go paint a room," you'll need to ask me a lot of questions, like:
Which room?
Where's the paint?
Where are the brushes?
Should I use a dropcloth?
In short, you won't be able to complete the task without help from me. If you have to depend on me every time, you won't be a very flexible painter. One way to deal with that problem is for me to give you all the stuff you need at the outset. Instead of "go paint a room," I'll say "please paint room number 348 using this bucket of paint and this brush, and don't bother with a dropcloth." Now, you've got everything you need, and you can get right to work with no further help from me. You're a much more flexible worker because you no longer depend on me.
The same thing applies to view controllers (and objects generally); it's better to give them everything they need than to have them depend on a particular object like the app delegate. It's true not just for managed object contexts, but for any information they need to do their job.
This is mainly because you want to use dependency injection with your UIViewControllers instead of just grabbing everything from UIApplication, this keeps your delegate clean instead of full of reference hacks.
This is also to keep with the MVC pattern:
Model
View Controller (Only for view logic)
Controller (For coordinating between the view and the model)
I tend not to agree with this pattern.
First of all I try to treat Core Data as an implementation detail, and as any implementation detail it should be hidden behind a good facade. The facade is the interfaces I expose for my model objects. For example if I have two model objects; Cource and Student, any cource can have a number of students. I do not want to let the controller take upon the duty to setup predicates and sort descriptors, and jump through all Core Data hoops just to get a list of students for a particular class. There is a perfectly valid way to expose this in the model:
#interface Cource (StudentAccess)
-(NSArray*)studentsStortedByName;
#end
Then implement the ugly stuff once and for all in the Model class. Hiding all the complex details of Core Data, and no need to pass around managed object contexts. But how would I find the sources, it has to start somewhere right? Yes, it does but you need not expose it to the controller. Adding methods such as these are perfectly reasonable as well:
#interface Cource (CourceAccess)
+(Cource*)caurceByID:(NSString*)courceID;
+(NSArray*)allCources;
+(NSArray*)courcesHeldByTeacher:(Teacher*)teacher;
#end
This also helps in minimizing dependencies between controllers. And reducing he dependencies between the model and controller. Assuming I have a CourceViewController and a StudenViewController is I did not hide the Core Data details behind a facade and wanted to pass around the managed object context as well, then I would end up with a designated initializer like this:
-(id)initWithManagedObjectContext:(NSManagedObjectContext*)moc
student:(Student*)student;
Whereas with good a good facade I end up with this:
-(id)initWithStudent:(Student*)student;
Minimizing dependencies behind facades, in favor of dependency injection also makes it much easier to change the internal implementations. Passing around the managed object context encourages each controller to implement their own logic for basic stuff. Take for example studentsSortedByName method. At first it might be sorter by last/first name, if later changed to last/first name sort you would have to go to each and every controller that has sorted students and make the change. Where a good facade method requires you to change in one method, and all controller automagically get the update for free.
The Apple Docs try to foster the most widely applicable and sustainable design patterns.
Dependency injection is preferred because it allows for the most flexible, expandable, reusable and maintainable design.
As apps grow in complexity, using a quasi-singleton like parking the context in the app delegate breaks down. In more complex apps, you may have multiple context tied to multiple stores. You might want the same view-controller/view pair to display data from different context at different times or you may end up with multiple context on different threads/operations. You can't pile all those context up in the app delegate.
If you have a simple app with a single context then using the quasi-singleton with the app delegate can work well. I've used it on several smaller apps in the past without immediate issue but I did hit scalability problems on a couple of apps when the apps grew overtime.
Which pattern to use depends on your shipping constraints and you best guesses about of the evolution app over its entire lifecycle. If its a small one shot app, then the app delegate quasi-singleton will work fine. If the app is more complex, might grow more complex or might spawn other related apps that will reuse existing components, then dependency injection is the way to go.

Resources