In MVC where do you put references to your model Classes? - iphone

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"!

Related

single controller managing a model and multiple viewcontrollers?

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.

iPhone MVC. Problems with the model

I'm new to programming, iphone application programming in specific. After reading a bunch about MVC I decided to give it a try in a small application. As to my understanding, MVC works like this:
Model: data, manipulating data, retrieving data.
ViewController: formats data from the model (NSDate to specific style), etc.
View: the actual gui.
If this is indeed a correct formulation of basic MVC theory, my confusion lies in how data is passed between the model, VC, and view. Example: if I make calls to twitter and get the data in the model, how do I (correctly) pass this information to the VC for further work. I know that between the VC and View one mostly uses IBOutlets. The Model is my real problem.
In my last app I made an NSString variable in the app delegate so I could access that data from any class. However, I read that this is not the best approach when the app becomes complex because the delegate is in charge of starting, ending the app, not holding data.
I've read of delegation methods, singleton's, NSNotification (which I've used to call methods in other classes). The problem is that I don't really understand how to use these techniques to pass data from the model to other views.
Please let me know if my question is unclear.
If you think about reusability, the main components that can be reused again are your model objects and view objects. They can be moved to different apps and still used properly. Your view controller is what is really specific to your app and where most of the app logic lies.
So in your example, you could have a twitter object that stores information and tweets from a user perhaps. You would create that class with all its functions separately within its own .h and .m file. Then in your view controller, instantiate the twitter class with data that is retrieved and begin using it from within the view controller.
Your view controller is actually retrieving the data but your model object is the one maintaining the data. In this way, you can pass on the model data with your twitter object to other view controllers.
Control over the application resides in the controller, so it is the object that will retrieve or save persisted data, update views with that data, and handle various events. Consider it the glue between the model and the view!
For example, if you were to click on a button to open a new modal view, you'd handle that event in your view controller. In the method that responds to the clicked button, you will create or access the new view controller and present it using presentModalViewController:animated:. If that new view and controller needs data that your current controller has access to, you could set a property in the new controller to refer to the object.

Passing Several NSStrings to another view - Iphone

In my iPhone app, the user will be making multiple NSStrings. Once these are made, I need to pass them to another view completely in the app. How can i do this? All I know at the moment os I can't access objects or variables declared in one view, in another. Thanks.
One way would be to follow the MVC (model view controller) design pattern. Whichever controllers are responsible for your respective views can then store and retrieve the NSStrings from/to a common data model object.
As to how you can make the strings stored in an object visible to the outside, the easiest way is to use Objective-C properties to save you from writing the accessor methods yourself.
I hope this helps with your problem or at least gets you started in the right direction.
Place the strings in a data model object (the M of the MVC pattern), with accessor methods (getter and setters, which can be automagicly created by properties). Then create and place that model object in some central location, a controller common to all views requiring that data, or the appDelegate, a reference for which can be found from any view.
Josh,
I would add to the MVC thing, that still you can do this in several ways.
What I would do for example, is to make your other "View Controller" (MVC), to "observe" when does the user create a new string, and to fetch it accordingly. In that way you would reduce coupling and it will be a cleaner implementation.
Another way would be to create a "delegate" so that the First View controller, "notifies" or calls the delegate method that you created, each time the user creates a new string ( again reducing coupling )

Having Freudian child parent problems with my objects. Need some pointers and/or Reference?

I think I have a basic question that is sort of hard to look up, I think.
Objective-C for Iphone.
I want to create two view controller instances that message and update an instance of a Model Class. How do you do this? I would prefer no using singletons. It's basically an "I really want to learn from you guys because this is awesome and I want to be awesome too!" question.
I would prefer we keep app delegate, singletons, nsnotification center out of the picture. App delegate specifically in that I dont think I wnat to have my data object created by app delegate, but I may have to.
The way, as I understand it, this works is sort of like this. Navigation Controller creates instance of FirstLevelViewController. My FirstLevelViewController creates instances of my SecondLevelViewControllers and then when told to pushes them onto the navcontroller stack.
I have my Model Instance being created by my firstlevelviewcontroller instance. Is that wrong? I think I need a reference to the instance passed to my secondlevelviewcontroller, but I'm having trouble because I can't figure out what the instance name of the firstlevelviewcontroller is (I think NavController instantiated it).
Help is so very much appreciated.
Assuming the model stays the same object (it can be mutable but not deallocated within the lifetime of BOTH view controllers), one might use a separate variable in each view controller to point to the same model class, with each view controller not knowing about the other. This is of course dependent on your application specific logic -- if one view controller 'knows about' the other than of course it makes sense to have the model be 'owned' but the independent one, and accessible to the dependent one via properties. However this considered bad because it promotes code coupling and dependency, which is looked at as poor coding. As to how both view controllers get the same model instance, typically it would be set (preferably in initialization) by whatever knows about them both, such as a higher level view controller, or if they are root view controllers, the app delegate.

Application Design and AppDelegate

I am developing an iPhone app for some sweet undergrad research I've been working on. Sadly, my school doesn't offer software engineering / design classes so when it comes to questions of best practices in OO Design, I do a lot of reading.
My Dilemma:
My application loads a view (v1) where, upon user's button click, v1's controller class executes an action method. This action method should fill an array with objects. After that, the user will either execute the action again or click a different tab to load another view. Other views in the application will use the array that v1 populated.
So, where should this shared array be declared? Right now, it's in the AppDelegate class from when I was testing features without a GUI. Should I grab the AppDelegate singleton and add items to it in the v1ViewController? Should it be declared as static?
Thanks for the help!
^Buffalo
EDIT:
Follow-up Question: When interacting with a singleton, which is the better way to talk to it:
[[MyAwesomeSingleton sharedInstance] gimmeSomePizza];
or
MySingleton *s = [MySingleton sharedInstance];
[s gimmeSomePizza];
I guess what I'm wondering is, do you make the sharedInstance method call every time or do you define a pointer to the sharedInstance and then reference the pointer?
Using the app delegate to store data that's shared between views and view controllers is reasonable and appropriate.
In my apps, I view the app delegate as the controller part of MVC, with UIViews and view controllers all being part of the "view". I prefer to use a variant of MVC called Passive View that keeps the model and view parts of my app strictly segregated with only the controller connecting them.
I'm assuming that the array of objects you're storing is your app's model, so storing them on your app delegate makes sense. As Daniel D said, there's no need to make it static.
The app delegate is really the heart of your program. You create and initialize your model and views in your -applicationDidFinishLaunching: method and save your model data and view state in -applicationWillTerminate:. When your view controllers receive events that changes your model, you can call methods on your app delegate to make those changes.
You could store it in an ivar in the app delegate. You don't need to make it static since the app delegate is a singleton anyways (there's never more than 1 instance).
If the app delegate is getting a bit complicated, you can factor out the data storage into a separate model object or perhaps use Core Data.