Pass Data Back in MVVM - ios

I've tried to implement MVVM in a CoreLocation/MapKit project. My main view controller solely derives data from other classes(view models) and displays them. No thinking is done in the view controller.
CoreLocation and MapKit delegate methods are all done in separate classes which pass data to the view controller when the app has been launched.
After the app launches, a model class prepares a path to be drawn on the map when the user starts the process. Even though the path is determined successfully, the path doesn't get drawn since I can't pass data back from model to view-model(MapKit class).
Also even if I could pass data, the view controller already created the map view when the app launched and now it needs to redraw it.
So how can I pass data back from model to view-model and redraw my map view?
P.S. my coding of choice is Swift

You can either use a delegation pattern to notify a delegate class that the model has changed or you can use NSNotification. The latter works better if multiple observers need to know about updates.
In my opinion, however, the MVVM pattern doesn't really work on iOS because it doesn't support UI data binding, so the View-Model doesn't really buy you anything except for added complexity. MVVM originated in the Windows world where there are UI data binding frameworks.

Related

In iOS, is it a good pratice to build an generic UI Component using UIViewController?

If I want to build a generic UI Component (one that will handle its own view and logic, data source,
etc), is it a good practice to subclass UIViewController?
I would say no. But it depends. If your component manages other view controllers or has/will have any kind of logic that's not specific to a view (e.g. navigation logic, business logic etc) , then you should subclass a view controller. Then again that makes it more than an UI component.
Otherwise, you should subclass an UIView, like Apple does with many components, including UITableView (speaking of datasource), GLKView, UICollectionView.
My overly simplistic answer is "no, when building a generic component do not automatically start with a UIViewController subclass". However that alone is not a useful answer and in some cases a UIViewController subclass is exactly the right solution.
Instead let's consider how to decide what your component should be. I think the best way to figure that out is to answer three questions:
What is this component responsible for?
How do you want to interact with it?
What are its dependencies?
In all cases we can try to start as simple as possible and add complexity only when the answers to those questions require it.
Could this component just be a function? No objects, no classes, if all you want to add is some behavior then maybe all we need is a function. If this behavior only applies to specific existing types then maybe we need a category on an existing class.
Not enough to cover what we want to do? Ok, I guess we might be talking about a new type so let's create a class. Can it just be a subclass of NSObject?
Want to display something in a view? Ok, then we at least have a UIView subclass, maybe a UIControl subclass if it is more interactive.
The view needs some data to back it? No problem sounds like we now need two pieces; a view to display data and a data source to provide it. Here the view shouldn't need to know who creates and owns this data source. As long as one was provided to the view we can use it, anything else is outside of the view's area of responsibility. Similarly we might add a delegate to notify some other object of interactions with the view.
If we still haven't covered all of this component's responsibilities then maybe we need yet another piece, something in the controller layer to manage our view. We're still not (yet) talking about a UIViewController though! It's fine to have a "controller" or "service" that is a NSObject subclass. If all this piece needs to do is manage network connections, or map NSFetchedResultController results to our view's data source protocol and update the view, or just provide a convenient implementation of the most common mapping of model objects to the view's data source then a simple "controller" object is still all we need.
Still not enough? Finally we get to the point where we consider providing a UIViewController subclass. Maybe we want to allow users of the component to just present a modal view controller to hand off responsibility for an interaction (send an email, compose a tweet). Maybe there's a common set of default behaviors we want to provide that are tied to view controller life cycle events (UITableViewController flashing scroll bars in -viewDidAppear:).
Build your component from the pieces you need to support the behaviors you want to provide but keep it as small and simple as possible.
Yes, it's good practice in many cases. The iOS SDK contain many examples of UIViewController subclasses. A few of them contain only a small amount of generic behavior and are essentially useless without customization:
GLKViewController
UICollectionViewController
UITableViewController
And some of them provide significant generic behavior but are still mainly containers for your own view controllers:
UINavigationController
UIPageViewController
UISplitViewController
UITabBarController
But most of them are essentially complete packages with little or no need (or ability) to customize their behavior:
ABNewPersonViewController
ABPersonViewController
ABUnknownPersonViewController
EKCalendarChooser
EKEventEditViewController
EKEventViewController
GKAchievementViewController
GKFriendRequestComposeViewController
GKGameCenterViewController
GKLeaderboardViewController
GKMatchmakerViewController
GKTurnBasedMatchmakerViewController
MFMailComposeViewController
MFMessageComposeViewController
MPMediaPickerController
MPMoviePlayerViewController
PKAddPassesViewController
QLPreviewController
SKStoreProductViewController
SLComposeViewController
TWTweetComposeViewController
UIActivityViewController
UIImagePickerController
UIReferenceLibraryViewController
UIVideoEditorController
If you think about what all of these have in common, you may conclude that they all have two things in common:
Each has a specific model (in the MVC sense) that it interacts with, and that model is not specific to your app. The models vary widely (UIVideoEditorController's model is a single video; UIImagePickerController's model is the entire photo library; GKAchievementViewController's model is a database possibly on an Apple server in “the cloud”), in some cases you provide the model (or some properties of the model) up front, and in some cases you receive the model (or a fragment of it) at the end. But in every case, the view controller handles all the interaction between the user and the model with little or no ongoing help from your app.
Each provides its own view hierarchy, with little or no customization required (or even permitted).
In other words, each of these view controllers isn't just the “C” of an MVC pattern. It's the tip of an entire MVC iceberg.
If your component is also an MVC iceberg, then exposing the tip of your iceberg as a UIViewController subclass is quite appropriate.
It depends on the iOS version you used.
A. prior to iOS 5.0, It's not a good practice, and not recommend.
B. start with iOS 5.0, It's just ok.
subclass a view controller for a UI component (UIView), , that means you wanna use the view controller life cycle method, to manage the user interaction and view display procedure, data model etc. So, if the life cycle method can not easily automatic called, the view controller is not that meaningful.
start with iOS 5.0, it's possible to create custom view controller container, so, it's ok to build custom generic ui component with view controller to add as a child view controller.
prior to iOS 5.0. Subclass a UIView with custom delegate protocol is the right way. one other thing is about the code organize. put the all custom delegate method to another custom class, not in the view controller, in the view controller just init a delegate class instance, and set this to the view delegate property.

The correct way to communicate between several different view controllers in Objective C

I have an app that was extremely simple until today. It had a tab bar view controller with 3 tabs. The middle tab was a camera, and the other 2 were table views. The tab bar view controller was the central hub for all the data in the app. So from there, I would set a table's data array as:
(PLEListViewController*)[self.viewControllers objectAtIndex:0] setList:newList];
Obviously, PLEListViewController is my UITableView subclass.
So now, I want to wrap the table views in a UINavigationController, which is fairly simple. But now, that line of code turns into:
[(PLEListViewController*)((UINavigationController*)[self.viewControllers objectAtIndex:0]).topViewController setList:newList];
There are 15 lines in the code that do this, which is not pleasant.
So my question: what is a more elegant way of doing this that I'm missing?
It's good that you're asking this and seeing the issue now. Your problem is can be found in your question. The answer to "the correct way to communicate between several different view controllers in Objective C" is "don't." Specifically, your mistake is here:
The tab bar view controller was the central hub for all the data in the app.
A view controller should never hold any of the data in the app. Your data should live in your model classes. All the view controllers should talk to the model classes. They should very seldom talk to each other. That's the heart of MVC.
So, you move your "list" (whatever that is, doesn't matter) into some model object that all the view controllers know about. That model object can be a singleton, or often better, it can be passed to the view controllers when they are created. When things change, you change the model. And in viewWillAppear: you update your view controller to match the current state of the model.
Never assume that a view controller exists when it is not currently on screen. If your design requires that a non-active view controller exist, then your design needs fixing.
You need to work with your architecture. Make the appropriate datasource and delegation protocols to ensure your classes can communicate anonymously. What you currently have is very inflexible and it will get worse as your app grows/changes.
You want to make things more loosely-coupled, instead of coding explicit traversal of links between your objects in your code.
Assuming you have one data model that is displayed in various places in your application, I think there are 2 approaches that could help...
One is to use your view controller hierarchy.. For example, use [ self enclosingTabBarController ] to find your closest parent tab bar controller and get it's data model property. Substitute -enclosingTabBarController with what works better for your application.
The other approach would be a "data model as a singleton" approach. For this you can either
move the data to your application delegate and access it via ((MyApplicationDelegateClass*)[ UIApplication sharedApplication ].delegate).dataModel
or
have a singleton data model object for your app, and access it via [ MyDataModelClass sharedModel ]
In any case you are moving to a looser coupling, which requires less explicit traversal of links between objects in your app. Less is more!

Trouble understanding viewControllers in iOS

I'm new to obj-c/iOS and I'm having trouble understanding conceptually at least viewControllers. I've read a lot of the Apple Doc's, I've even used viewControllers to some extent in xCode, but I still don't quite get what they are, or what are the best ways to use them.
I've been an AS3 dev for many years so my mind works in the context of MovieClips/Sprites and the Display list to get graphics on the screen.
Ok so from my understanding...
A viewController is a kind of class that handles graphics in some
fashion and then allows you to do something with them?? What is it in it's most basic sense?
You seem to add viewControllers to a Window class, which I guess is a bit like
adding a display Object to the Display list?
What is it that a viewController does for you in it's most basic sense?
Are there certain things you definitely can't do with them or shouldn't do
with them?
Do viewControllers need to be connected in some way to the rest of the iOS framework to function (apart from being added to a window).
How exactly do they use data? (I've read up on MVC, I understand that conceptually this is a slightly different question) as I understand it you don't hardcode data into a viewController, so how does a viewController access any static data?
Let's say I just wanted to throw an image up on the screen, exactly what part would the viewController play in that process? is it just something which handles only one small aspect of that process or is it the whole show and handles everything?
Does one viewController handle multiple images? is it like it's term, a "controller" for all the images presented on screen, or does it handle one image at a time?
What is a viewControllers connection to the image(s) it handles? it contains references to them?
I'm using the Sparrow framework which is helping but I would still like to be able to get my head around what viewControllers are so I know how to use them properly.
Ha, I apologise for the above I know it must look like I'm completely confused :) thanks for any advice.
Hope this helps you:
A viewController is a kind of class that handles graphics in some fashion and then allows you to do something with them??
It's the glue between a View (Xib File) and the Data (Could be
CoreData or whatever you're using in the backend). All the UI Elements
you are using in the View you normally define as properties in the
controller to get access to them.
What is it in it's most basic sense?
You seem to add viewControllers to a Window class, which I guess is a bit like adding a display Object to the Display list?
I don't really know AS3 so I cannot compare Display lists with ViewControllers. But basically ViewControllers are there to handle
different types of transitions between the views and accessing
(setting/reading) the data which is displayed in the view.
What is it that a viewController does for you in it's most basic sense?
Like I've written above. Most basic sense they interpret what the user
does on the view and depending on the action of the user changes the
model.
Are there certain things you definitely can't do with them or shouldn't do with them?
It is always hard to keep the border between model and controller.
They are pretty close to each other. So what I normally try is to
delocate all logic stuff (like calculations, database access and so
on) this does more belong into the model part. But of couse you're
using these external classes in the controller.
Do viewControllers need to be connected in some way to the rest of the iOS framework to function (apart from being added to a window).
Well like you already have written the ViewController needs to be
connected to a view. Otherwise it would not make much sense. There are
different subtypes of UIViewController such as UINavigationController
where you probably need to overwrite some other methods to provide the
whole functionality wanted by these special subtypes.
How exactly do they use data? (I've read up on MVC, I understand that conceptually this is a slightly different question) as I understand it you don't hardcode data into a viewController, so how does a viewController access any static data?
There could be different approaches to store the data. Simplest way
would be to have the data directly stored in the UIViewController.
This could be a custom class which is the container of the data. All
changes are directly written into this class and displayed by the
UIViewController. But in most of the cases it makes sense to use
CoreData (Which is responsible for reading/writing the data into a
sqlite database). You could look at CoreData as your model and the
UIViewController gets the data from there and passes the data which
the UIViewController has received from the View back to it.
Let's say I just wanted to throw an image up on the screen, exactly what part would the viewController play in that process? is it just something which handles only one small aspect of that process or is it the whole show and handles everything?
The UIViewController would store an internal Property (UIImageView *)
which is in the Interface Builder connected with the UIImageView you
have created in the Xib file. So over these property you can change
through your Controller the image.
Does one viewController handle multiple images? is it like it's term, a "controller" for all the images presented on screen, or does it handle one image at a time?
Yes, this isn't a big problem. You can have as many images you want.
You just need to have the properties defined in the UIViewController
and linked to the View.
What is a viewControllers connection to the image(s) it handles? it contains references to them?
Yeah, its like a reference to the UIElement. You can then change
whatever property of the UIImageView you want directly from the
UIViewController
Some useful links:
Apple Official ViewController Guide
Apple Official ViewController Basics
You should have a look at Storyboards (U can use them since IOS 5.0)
I recommend you to check:
https://stackoverflow.com/questions/1939/how-to-articles-for-iphone-development-and-objective-c
Here are the answers to your questions:
No, it's doesn't handle graphics. It's the controller of the MVC design pattern. It handles the lifecycle of it's contents (for instance the views) and the data linked with.
A UIViewController is set as a root of an UIWindow. For instance, a UINavigationController is a subclass of UIViewController that stacks UIViewController in order to deal with the navigation.
Response in (1)
Try to be more specific with this question please.
As already commented, it's useful if you use the already built-in components like UINavigationController or UITabBarController.
For instance, you can have the data in instance variables and the display them in the contained UIView.
The UIView attached to your UIViewController will contain an UIImageView. Your UIViewController would have a connection with it in order to whatever changes you need, for instance, changing the image when the user press a button.
It can contain multiple UIViewsand therefore multiple UIImageViews (it's a subclass of UIView)
As commented, they would be contained on an UIImageView and would be linked programmatically or with an IBOutlet.
In a nutshell, a view controller is the controller in the MVC pattern. Please check this link before reading further so you're up to date with this pattern:
http://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/MVC.html
OK, basically a controller manages a collection of views. It also fetches data from your model and sets the state of the views. It's important to note that the views know nothing of your model (your data), and the model knows nothing about your views. A controller also receives events from the views and decides how to change your model accordingly. It is essentially managing the synchronisation between your views and model.
There are technologies that help automate this such as KVO and key value binding. A google search will help you there.
One more thing. No other part of your application should access your views except for the controller. So generally in an application controllers tend to communicate with each other, for example via transitions or the delegate patterns between controllers under a navigation controller. So your application backbone tends to be controllers talking to each other.

iOS: Handling of data

Explanation
My app basically uses a mapview with an overlay of polygons that represent buildings, coupled with an annotation. So for this it imports a custom class called Annotation that handles the popup details when the annotation is tapped, meaning it store the building's name and address. At this time the callout (the blue disclosure button) loads an empty DetailViewController object (as there's not really any data to pass through).
I soon added a new feature in the form of a searchable table that loads custom objects of the Building class (with similar properties to Annotation, plus images and more details) that then loads in the aforementioned DetailViewController class with the building's details.
So to summarise, the MapVC contains multiple annotations, which when the relevant disclosure button is tapped open the DetailVC. SearchVC is accessed by a button on the MapVC and has a table of Building objects, which loads a DetailVC with the relevant data, like so:
Next Step
So now I want to implement functionality into the blue disclosure button on the callout, so when the user taps it it'll load the building details. At the moment all it has is the annotation's details. I could add the extra properties to the annotation to make it complete but I think it's much better to just work with one custom class called Building, which has a MKAnnotation nature. Then this Building class is loaded for the annotations and searchVC's table.
Question
So finally, what's the best way to go around this? I want all the data to be stored independently of any of the VCs in the diagram. I followed a tutorial from Apple (the BirdSighting one) which uses a separate Datacontroller class, which I'd then load into other classes. Is this the best approach?
You're talking about MVC, model-view-controller. This is a very smart way to handle things, and is a good practice to get into. The model stores the data, in this case, building names, etc. The view displays data. The controller is what connects the view to the model, updates the view, gets notifications from users and in turn updates the model.
I use a singleton pattern for model data. Only one instance of a singleton is ever present in an application. That way, the data is not bound to any one particular view controller. Data only gets updated in once place, the model. It's a lot easier to trouble shoot issues with a singular point of convergence for application data objects.
I have a macro that I define in my PCH file.
#import "DataController.h"
#define DATA() [DataController sharedInstance]
In my code I can easily get to my model class by calling
DataController *data = DATA();
All of my views and viewcontrollers access objects stored in DataController, so there are never two view controllers handling separate pieces of information independently. All references point to the same place.
Some people use the AppDelegate object to store data, but it can quickly turn into a 1000 line beast. I prefer to keep the AppDelegate clean :-)

What is the appropriate design pattern for the following situation?

As an exercise I am working on a simple drawing app for the iPad.
I am using UISplitView, with the drawing view as the detail view. In the master view controller I present (in a table view) a list of the shapes drawn so far.
The user can edit or delete any shape from the master view controller, and also select and edit a shape by touching it in the detail view controller.
To notify each of the view controllers of the changes made by the other, I thought of using delegates, but I am not sure if this is the right pattern to use.
First, as I understand it, delegates are supposed to be used when a certain object encounters an event which they don't know how to handle. in that case they pass all the information to the delegate and let it handle the event. This is not the case here since both view controllers need to do something with the information. Using delegates here can cause code repetition.
Another reason I am thinking not to use delegates is that in the future I might want other view controllers to get the information of changes in the drawing. I can use multiple delegates (is it good practice in general?) but I'm not sure this is a good solution either.
Are there other solutions I should consider?
On the contrary, I think delegates might be the right pattern to use here - you don't necessarily delegate only when you can't handle an event (though that might be one situation where you would delegate).
Instead, consider delegates a way of getting information to or from another object, when you simply don't know what that object might be. For example, Apple uses the delegate pattern when working with UITableViews; in that delegate protocol, the table view knows perfectly well what to do in each situation, but still notifies your code when certain actions are about to happen. I think that's an excellent parallel for your situation. (Note that a parallel to your question's assumptions also exists, in the UITableView "data source," where the table view does require some bits of information.)
Another technology you could consider using, if you're really dead-set against delegates, would be to use notifications. You can have each controller subscribe to particular notifications, then have your shape (or detail view controller) post instances of NSNotification when observable changes happen. That way, you still get to handle events happening in a different controller, but without needing to maintain a delegate list.
As for code duplication, just consider refactoring as you start encountering situations where you would duplicate; maybe you should design a single delegate or notification subscriber object for the common code, then only do class-specific things in each of the other controllers?

Resources