I don't understand : in all tutorials on iOS, it shows a classical 3 parts Model, View, Controller, then why does XCode prefix controller with xxxViewController instead of xxxController ?
This makes believe that the controller is just for the View and not for the Model and so close to MVVM than classic MVC.
In answers given it says it's not MVC.
But if I look at standford University course it clearly depicts iOS development as classical MVC in Lecture1.pdf # http://www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2010-fall
Xcode doesn't do this for all controllers, Just for view controllers (which are subclasses of UIViewController). It makes it easier to find which ones manage views, You can create other controllers and name them what you like.
As g_wolfman comments in this Apple discussion thread:
Despite Apple's use of the term MVC in their developer documentation,
they don't actually use it; they use a variant of
[Presentation-Abstraction-Control
(PAC)|http://en.wikipedia.org/wiki/Presentation-abstraction-control].
The key difference is that in MVC, the view gets information directly
from the model and the controller is only concerned with changing the
model. Hence the view may need to know how to transform data from the
model as part of creating the view. In PAC, the view and the model are
completely isolated from each other; everything passes through the
controller. This allows the view to be written in such a way as to
avoid needing any "business logic".
EDIT - --
from apple doc - http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaDesignPatterns/CocoaDesignPatterns.html#//apple_ref/doc/uid/TP40002974-CH6-SW1
Combining Roles
One can merge the MVC roles played by an object, making an object, for
example, fulfill both the controller and view roles—in which case, it
would be called a view controller. In the same way, you can also have
model-controller objects. For some applications, combining roles like
this is an acceptable design.
Related
I have a general working knowledge of object-oriented programming and I'm currently trying to create an interactive novel program in Objective C using Xcode 4.2 with storyboarding.
I have a storyController class that instantiates the page objects and a viewController class that needs to display the pages. My fundamental question is the best approach for my storyController to tell the viewController to update it's text to display that of the new page object. My instinct tells me that my storyController needs to call a method on the viewController and pass it a page object. However, I'm not sure how to reference the view controller since it seems to be automatically created and linked by the storyboard (I don't see the viewController instantiated in the appDelegate).
I've read this post: http://www.iphonedevsdk.com/forum/iphone-sdk-development/54859-sharing-data-between-view-controllers-other-objects.html and it seems to address the issue. I could make a shared object on my appDelegate and use KVN or NSNotification to tell the view controller to check it.
I've also been reading about delegates and protocols as possible solutions.
So considering these potentially different approaches, which would be best to tell my viewController to update itself and pass it an object that contains the updates?
I would suggest looking at the UIPageViewController class, which probably will do a lot of the heavy lifting work for you, depending on the specifics of your app. This class is essentially a controller class that contains multiple viewControllers. Each managed viewController becomes essentially a "page" in your book.
Here is a tutorial using UIPageViewController.
If this approach won't work for your app, I'd still suggest using a separate viewController instance for each "page" of your book and handle the transition between the pages with segues.
I'm particularly interested in how to follow Apple's standards with respect to a good MVC pattern design. Let me illustrate my question with an example.
Lets say I have a number of fairly complicated UI elements on screen such as UITableView. Basically these elements require a datasource and a delegate to handle interaction.
There are two approaches to working with this.
I can have the same subclass of UITableViewController handling all of the elements and dynamically handling things based on the requesting UITableView.
Second approach would be to have "lightweight" controllers that would manage each individual view. In iOS 4.x you're not allowed to have multiple UIViewControllers, so these controllers would be more for managing state and interaction.
I don't like the first approach because it doesn't scale and seems to combine things. What if I have multiple complex objects of dissimilar type?
The second approach seems better. Objects are encapsulated better - separation of concerns. The only downside seems to be increased complexity of communication. Lightweight controllers would have to either delegate back to the real view controllers or they'd have to have a handle to something to perform real actions.
What is your experience with either of these approaches? Is there a better solution for decomposing a complicated interface?
Thanks
You can always re-assign the delegate and datasource of a UITableView to something else. It does not have to be a UITableViewController. As long as it fulfills 1 of the protocol methods for the delegate and datasource.
So you may have a UIViewController (controller) that is powered by a nib/xib (view created by Interface Builder). In that interface you've added a tableview and set it's delegate and datasource to the file owner (back to the controller).
Then the UIViewController may communicate to Core Data (model) to retrieve related objects in response to the UITableView delegate messages.
Or, the UIViewController can re-assign the delegate/data-source to a lightweight provider that fulfills the protocols to make it more encapsulated.
This is the style of MVC Apple is suggesting.
I'm working on an app that has multiple view controllers for different screens and the whole app is about displaying data from an sqlite db.
My inicial design was to have a db object (the model), a main controller with exclusive access to this model and have all other view controllers merely manage visual aspects of windows,buttons,whathaveyou.
But I'm having a hard time realizing how to make the main controller be aware of all other view controllers throughout the app's life in the context of apple's ios app architecture.
I've thought of 3 approaches so far:
1 - NSNotificationCenter and have the main controller observe all other controllers?
2 - make the main controller delegate of all others? Though I'm still not clear on how to define a delegable (did I make this word up?) protocol in general. That is, even for objects that don't have a setDelegate method.
3 - passing an db object around to each view controller. Though this seems a bit like playing C passing state around..
Any thoughts?
Thanks!
Your approach should probably be one where the view controllers and models are as ignorant of each other as possible. This is a pretty common design pattern, I believe. You should have model objects that represent each logical "object" in your domain. Those objects may just be state. Next, you might want to create a controller (like you mentioned) that has access to your database and can make queries. The result of those queries should be used to construct instances of your logical model objects (e.g., XXPerson) and hand them off to whatever made the query. Given that, each view controller in your app should do the following:
Create its views and lay them out as appropriate
Instantiate your database controller object (and possibly hold on to it for further use)
Query the database for the data it needs via the database controller object
Use the resulting data (which should be returned as your logical model objects) to adjust the views or do whatever you need with them
Note that you could make use of a singleton for your database controller, but the singleton pattern is a loathsome one if you ask most good developers. :) Instead, there's really no reason why your application can't just create an instance of your database controller as needed, use it for some queries, then discard it afterwards.
Internally, of course, your database controller class should have singular, static access to the database and possibly synchronize access to write methods so that you don't run into issues with concurrency.
There are many possible design approaches, but one in which things are loosely coupled means that there isn't a bunch of interdependency going on, which is always a good thing. Let your model objects, database controller objects, and views all be independent of each other. The view controllers, of course, are the bridges that tie all those independent concepts together into a functional product.
That's my opinion, anyway. :)
It sounds like you're looking for a Data Access Object or service/store as part of your controller layer. I think that's a good idea and a common pattern in other languages that for some reason seems widely ignored in iOS apps.
Provide each of your view controllers with some object which manages access to your data store. You might want to only construct a single instance of that store but your controller's don't need to know that. As far as any individual controller is concerned it was given an object it can use to get and store model objects.
I don't think you should try to prevent your view controllers from accessing model objects at all. Rather introduce a service so that your view controllers don't need to know the details of how to load or persist those model objects. If necessary you can use that service to translate between one model and another if you find the need for a view-model or don't want your view controllers to work directly with whatever model objects you persist.
I think that a dependency like this should be a strong reference rather than a delegate and provided to each view controller when they are constructed via constructor-based or property-based dependency injection or some inversion of control container as appropriate for your app.
Having worked through some tutorials on some basics via the iPhone, I'm struggling to determine how best to structure my code. The book I'm using points out things like "you wouldn't normally put this here, but for expediency...". Well, I'd like to know what one would "normally" do.
My application is somewhat simple - there is a table view showing a list of objects and one can add, remove, edit these objects (I plan to provide a more sophisticated organizational scheme later, but I'm keeping it simple to get something working).
So, I have a RootViewController that extends UITableViewController. When the "add" button is clicked I push a subclass of UIViewController onto the stack (this class is the "add/edit" form for my objects). I have a simple data structure-style class to hold the fields of the objects.
The apps like this in the book basically put an array inside the RootViewController and use a reference to the model class to represent the "object being edited". Basically, the models are all wrapped up in the view controllers. This seems wrong.
So, my question is: where do the models and the objects for managing them normally live?
And, does the answer to this depend on how I'm storing my objects? I have not done much with CoreData, though my plan was to use it for persistence of my objects. Will the hooks and boilerplate provided by XCode make this a nonissue?
Best answers will be pointers to some best practices type stuff, which I wasn't able to easily find via Google or on Apple's Dev site.
First of all you are right about your intuition that it seems wrong. As you described the model is stored in the view controllers. That is a bad idea. By doing so you are violating the model-view-controller paradigm, which makes your code hard to maintain.
So what you need to do now is get your model in a separate object or tree of objects or even better use CoreData, which is also great in terms of memory management.
As you want to use CoreData you should have a look at the UIFetchedResultsController class which you will use to obtain the objects from the managedObjectContext which will be your model.
What you would do in your table view - detail edit example is:
Fetch the contents of the table view using a fetch request and setting it on the NSFetchedResultsController you hold as an instance variable in the rootViewController
Set this rootViewController as the delegate of that NSFetchedResultsController
If an item is checked or the add button is pressed push your detail view controller on the stack, pass the object to be edited with it, or nil if it is a new object. Also pass the managedObjectContext to the detailViewController. Update or create the object.
Implement the delegate methods of NSFetchedResultsController in your rootViewController and there you reload the contents of the table when necessary.
What you gain is a nice and clear separation of model (CoreData's managedObjectContext) the controller (rootViewController and detailViewController) and you views. If you now edit an entry by using the detail view, your rootViewController is notified via your NSFetchedResultsController and automatically updated. What you also gain is that you do not have a strong reference among the viewControllers in your application.
Btw, you set up your CoreData stuff in the application's delegate. There is a lot of boilerplate code around in Xcode and on the ADC. Check out the Recipies app [1] in which this approach I just descriped is used. There are also some videos about CoreData on Apple's developers site.
[1]: http://developer.apple.com/iphone/library/samplecode/iPhoneCoreDataRecipes/Introduction/Intro.html CoreDataRecipies
I have been wondering for a while, after asking different people and without any of them providing what I would call an "at least a bit concrete answer":
Question:
Where, in an iPhone application should an application keep the references to it's Model Classes (using the MVC approach) ?
In iPhone (and Cocoa) applications we have what we call the "App Delegate", which basically start's up our application and inits our controllers, also handles UITouch events.
So is the App Delegate a controller ? a model class ? none of the two ? I think not knowing that also makes confusing to know where to put the Model References.
Example:
You have the Application Delegate, that delegate contains a reference to your Application's View Controller. If my Application would use Model Class A ( which is a webserver daemon class ), and a Class B which stores data queried by that webserver.
Where would you guys store the references to A and B ? (App Delegate ? View Controller ? Both ? )
There are many options here, but as an example, I would really like to know how would you guys use mvc to put together this application which only uses one View.
It is tempting to put everything in the AppDelegate, but if you start doing this, then your AppDelegate will be full of reference hacks. If you are doing a strict MVC, then you should have 3 things:
A Model
A View Controller (Only for view logic)
A Controller (For coordinating between the view and the model)
So for example, I have a model Foo and a Foo controller. I would have:
Foo.m (Model)
FooViewController.m (Displays a Foo)
FooController.m (Controls the logic)
And finally, to answer your question, I would store my references to Foo's in the foo Controller. I like to use singletons for my controllers, but thats just me. If you do use a singleton, you can just do something like this: [[FooController sharedInstance] listOfFoos] to get your Foo's
In my applications I usually rename the AppDelegate class to AppController, if that helps explain things better conceptually. Your app controller is responsible for creating and/or configuring the model controller (which manages your collection of model objects) and window or view controllers, setting up references between them if needed, and calling methods on these controllers in response to NSApplication delegate methods or high level action methods from the main menu. Depending on how complex your application is you might also have additional model or view controllers which are created outside your app controller.
Of course if you have a simple application there's no real reason not to have your app controller play the role of the model controller if you want. What you want to avoid is file with hundreds of lines of code, all doing conceptually unrelated tasks.
Traditionally the controller creates the Model and then initialises the View with that model. The controller then listens to changes in the model and view and coordinates the flow of the program through this. That would be my generic answer, maybe things in practice would be different for iPhone development.
Where, in an iPhone application should an application keep the references to it's Model Classes ( using the MVC approach) ?
The controller layer keeps references to the model layer.
So is the App Delegate a controller ? a model class ? none of the two ?
The App Delegate is a controller.
Where would you guys store the references to A and B ?
A and B are model classes that would usually be created and owned by the controller layer.
I would really like to know how would you guys use mvc to put together this application which only uses one View.
The purpose of the controller layer is to allow the model and view layers to be self-contained. The model shouldn't know anything about the controller or view layers. The view shouldn't know anything about the controller or model layers. The controller's job is to be a double-ended adapter to the model on one side and the view on the other.
I would set up your example app like this:
UIApplication delegates to AppDelegate.
If operation of your server class (A) is simple:
AppDelegate creates and owns instance(s) of server class A.
If operation of your server class (A) is complicated:
Create a dedicated controller class (C) to control the server.
AppDelegate creates and owns instance(s) of class C. One instance of (C) for each instance of (A).
Each instance of class C creates and owns one instance of class A.
AppDelegate creates and owns an instance of your ViewController class, which loads and owns your view.
It's not clear in the question what the purpose of class B is.
If it's a chunk of data that's for the use of A only (like config data or static website data), I would have it be created and owned by the server (A).
If it's data that is created during server operation and needs to be displayed in the view, then you will probably want something like:
A mutable array owned by A, to hold instances of B.
Another controller class (D) to reference that array and act as a datasource/delegate to your view.
I find that in most instances, AppDelegate provides a good place to place some base functionality (such as a a background image you want applied in every controller), but that you'll want to have additional controllers and model code elsewhere. A navController or rootController would often be placed as a property on your AppDelegate.
So, I would say that is somewhere between "neither" and "controller", but leaning more towards "neither". Definitely not "model"!