EDIT: Although the answers are teaching me things, I still have no
idea how I might "implement" a model. Can anyone give me an example as
to how I would create a simple model class that has a few basic
functions that make calls to NSUserDefaults or JSON web calls and how
I would access this from ANY of my view controllers?
I am just beginning iOS development and have come to the point where my app will require a Model to interact with the overall data flow between controllers, but am unsure as to how they should be implemented properly.
I understand that the View's are in the storyboard, and the Controllers are the classes associated with those views.
What is the proper way to implement a central Model for an app? Do i create a class (ie "MyModel.h/.m") and then import it from all of my view controllers?
I also see people using a UINavigationController->RootViewController as their model, is this viable?
I have googled this question and searched stack overflow for a few hours, but am now resorting to a new question.
EDIT: Although the answers are teaching me things, I still have no
idea how I might "implement" a model. Can anyone give me an example as
to how I would create a simple model class that has a few basic
functions that make calls to NSUserDefaults or JSON web calls and how
I would access this from ANY of my view controllers?
In iOS, a model (MyModel class) is usually a subclass of NSObject or in the case of Core Data (an iOS framework that helps save data to a database locally on the device) NSManagedObject. As with any model object it contains instance variables and getter / setter methods. Most object-oriented languages have a mechanism to provide encapsulation, in iOS a property provides encapsulation and the keyword synthesize automatically generates the getter and setter methods.
View is subclass from *UIView* which provides the capability for handling touch events and drawing.
The UIKit framework contains classes to draw typical interface elements such as tables (lists), buttons, textfields, sliders and more.
Controller is generally a subclass of **UIViewController** that manages a view, it is also responsible for responding to delegation messages and target-action messages.you can have a UITableViewController which is a subclass of UIViewController that manages a UITableView
TabBar and Navigation View Controllers manages an array of view controllers, but Navigation VC manages VC as a “stack” data structure and yes it is a viable usage
please have a look at Design Patterns in ios apple library resource for further reference and here is a apple sample code to understand how to create a network application using the Model-View-Controller design pattern
this tutorial teaches you how to get started with JSON , try integrating FB in your app for understanding JSON as its fun and easy
start coding NSUserDefault in your app for example
// create a standardUserDefaults variable
NSUserDefaults * standardUserDefaults = [NSUserDefaults standardUserDefaults];
// saving an NSString
[standardUserDefaults setObject:#"mystring" forKey:#"string"];
here is a good tutorial i started with..
happy coding :)
Related
I am working with cocos2d and CoreData. I have imported "AppDelegate.h" but I can't create an object from it. I would think that all I would do is:
AppDelegate *delegate;
When I do this it get an error saying AppDelegate is not defined. The AppDelegate .h and .m files are next to the main file.
Also, when I try to write to a file I don't get an error but it does not write.
The boiler plate code created by XCode (I'm assuming you are using XCode) will create an NSManagedObjectContext for you called *managedObjectContext. If you need to create other objects that are going to interact with your core data model (such as a view controller), you simply pass in that managedObjectContext object as an argument (or link it to a property in your custom class) and interact with it in your custom class. It's worth noting that it's not good practice to be passing around an AppDelegate object in your app. Your app delegate should be at the foundation of your code base and not treated as a typical class. There are definitely times when you will want (or need) to pass the app delegate as an object or reference it in IB, but typically your app will launch in your
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
method and you will launch your primary view controller from there.
Some things in core data also require the persistent store coordinator (such as retrieving managed object ID's), so you may need to pass that in as well. If you need some help working with Core Data, there are a bunch of great articles and books on the subject. I recommend reading as many as you can, since Core Data can be difficult to comprehend at first. It helped me to read a bunch of tutorials at first since everyone explains it a little differently.
Here's a great recent tutorial written on Bindings, Core Data, and working with the app delegate to get you started: http://www.raywenderlich.com/21752/how-to-use-cocoa-bindings-and-core-data-in-a-mac-app
In Cocos2d 2.0, AppDelegate is renamed to AppController
AppController *app = (AppController*)[UIApplication sharedApplication].delegate;
I am making a tabbed bar application that has a section for Quizzes (which are written in XML). I am trying to conform to the MVC paradigm so I created a parser-delegate class, and a class for a quiz object which contains an array of questions and an array of their associated answers. My problem is that my parsing method has no way of sending it's quiz objects back to the view controller. Do I need to set up a delegate for the view controller to communicate with the Parser? Or should I just set the view controller to be the delegate for the parser and not have a separate class for the parser delegate.
Note: I am using NSXMLParser..
Any input as to the best way to do this is much appreciated.
Is your problem that you UIViewController is already created when then parsing finishes, I would usually use NSNotifications for this. And then the UIViewController can wait for the NSNotification or your app delegate can and then pass it onto your ViewController. Alternatively you can use a delegate callback or a callback blocks if you are supporting iOS4+. Hope this answers your questions.
I am working on an application which uses a UITabBarViewController to hold two UITableViewControllers.
In the Story Board, I pull out the two UITableVIewControllers which are called firstTVC & secondTVC and then embed them in a UITabBarController.
I have a UIDocument #property with a fetchedResultsController in firstTVC that works great, but I haven't figured out how to pass the ManagedObjectContext #property from firstTVC to secondTVC.
I have thought about doing it in the app delegate, but I have read that it is considered taboo (especially in iOS 5).
Thanks for reading!
Caborca,
Apple's standard Core Data template maintains the MOC on the AppDelegate. Why do you have a problem using it? (Yes, some folks believe all singletons are "code smell.") That said, this is hanging off of a singleton defined by the Cocoa Touch framework. It already exists and is available everywhere in your code.
If that doesn't work for you and you are instantiating via nibs, then you are going to need to create a custom delegate or read the singleton and store it locally in your -viewDidLoad method.
Andrew
I'm coding my first app in XCode 4.2 supporting iOS 4.x through the current releases. To support iOS 4.0, I'm not using Storyboard feature and also using unsafe_unretained for weak references. I have AppDelegate files (.h and .m) along with several view controllers with UITabBarController. In my first view controller, in the -viewDidLoad method, I initialize two NSDictionaries and also start a timer with 1 sec interval. In the selector method, I have to pickup a random number between 0 and 7 to pick a corresponding value in both the dictionaries. The dictionaries are used only in the first view controller and not anywhere.
My first question is
where do I load those two dictionaries - in the AppDelegate -didFinishLaunchingWithOptions: method or in the first view controller's -viewDidLoad method?
I also wanted to support iPad. If that's the case, do I create a common class library to support iPhone/iPod/iPad?. If that is the recommended way, can I move the common functionality to the AppDelegate .m file instead?
Please advise.
You can move your common data and business logic into a separate set of model classes outside of the UI layers and appdelegates. This is one of the main benefits of the MVC pattern - by separating and making a clear distinction, it's easy to have separate view layers (one for phone and one for iPad).
That means all the data (dictionaries), logic with your random numbers and timers would be encapsulated and shared. That also allows you to cleanly unit test the majority model and logic programmatically. It also means you can make substantial changes to your algorithms and minimize the code churn.
When the timer goes off it can either post a notification or you can have a delegate pattern where it does a call back.
Related Post: Delegates vs. events in Cocoa Touch
If you do a shared model, one option is to use a singleton pattern where you access the model like:
[MyModel sharedInstance];
You should keep your code and data together if possible, which means that if you only access the dictionaries in your view controller then you should initialize them in the view controller's viewDidLoad.
I recommend keeping stuff out of the app delegate if possible or else you'll end up with a weird monster class that does too much stuff for which it shouldn't be responsible. If necessary, create one or more classes that manage common data (for example using the singleton pattern).
Whether you can/should use a common file for both iPhone and iPad depends on a number of factors. The main factor is: how different are the UIs? If they are very similar then use one class for both. You can also create a base class with common functionality and sub classes for iPhone and iPad which implement the necessary differences.
I have a strong j2ee background, and I am trying to move to objective-c for some desktop/iphone programming.
I used many java web frameworks with mvc in mind, spring and struts ecc... so I am used to have servlet or controller which pass attributes to jsp pages, which is the view.
In jsp pages with jstl you can call this attribute and render to video.
In this way controller and view are (in theory) clearly separated.
With xcode, I can easily recognize the controller and the view built with IBuilder.
All the tutorial I found, shown the controller which go and change directly labels or text fields.
So my two questions:
seems to me that there's no separation between the two (controller and view), where I am wrong in that ?
is there a way for a controller to pack all objects in a kind of context in a j2ee way and have the view read that context ?
thanks
Leonardo
In most of the examples you have read you probably saw something like this:
[myTextfield setStringValue:myString];
now in this case sure the controller is updating the textfield directly, however as myTextfield is usually an IBOutlet it can be any textfield in your view, or even nil. quite possibiy it doesn't even need to know that it is an NSTextfield just that it responds to a setStringValue method. In this sense there is a seperation between the controller and view.
Now in your comments above you were concerned with seperation of responsibilities within MVC but did not mention the model much. With Cocoa bindings you can bind directly to model keypaths, in this case the model neeed not know anything at all about the view.
MVC is a bit of an ambiguous concept with no hard definition. It can mean different things to different people. For me it means that the view has knowledge of the controller ( through outlets or bindings) limited knowledge of the model(through bindings). The contoller has full knowledge of the model and limited knowledge of the view(through outlets). Finally the model has zero knowlege of the view and ideally no knowledge of the controller.
With regard to your second question, I don't use j2ee, but I think you can acheivee what you want by having your controller update a context ivar ( probably a NSDictionary) then in your view bind to this context with a keypath. However there is no real need to wrap everything up bindings are very versitile and u can bind to any property.
I do not understand your second question (I've never used J2EE), but I think I can make some headway answering your first.
Cocoa does not enforce MVC; it just strongly encourages it -- especially for larger projects. Consider an example program, one that has an NSTableView bound to an NSArrayController.
In this case, the NSTableView is clearly the view (it has the word "view" in its name) and the NSArrayController is clearly the controller (it has the word "controller" in its name).
The model is an NSArray that the NSArrayController knows about, but you probably don't interact with that model directly. You will instead ask the NSArrayController to manipulate its model by sending addObject: and removeObject: messages to the array controller (and not to the array itself).
When you do this, the NSArrayController will effect a change in the NSTableView via bindings. Again, you don't ever ask the NSTableView to do anything.
So you never talk to the view and you never talk to the model. Everything you want to happen goes through the controller.
MVC. QED.
Of course, maybe the way your project works, the view should be its own controller. The world won't end, although you might find it to be a little more difficult to go against the grain of the framework. But you should always try to use the best approach for the job at hand instead of insisting on some sort of design pattern purity.