calling methods across view controllers - iphone

My question is about the best way to implement passing of information between UIViewControllers.
If I have an application with 2 ViewControllers and for example a user selects an item in ViewControllerA which should then show the item and more details in ViewControllerB.
What would be the best way to implement this? via the appdelegate? or by passing a reference to ViewControllerA into ViewControllerB? Appreciate any help or examples of the best way to do this.

ViewControllerA (VCA) would maintain a reference to ViewControllerB (VCB). VCB would maintain a reference to the selected object as an ivar. When the user chooses an object in VCA, VCA instantiates VCB (if not already instantiated), sets VCB's selectedObject property to that object, and then pushes VCB. VCB reads from the object assigned to its selectedObject property to draw its information into the view.
In VCA, for every one of the "items" that the user can select, there needs to be an underlying object instance backing that item. For example, a UITableView might be backed by an NSArray of Vegetable objects if the user is selecting from a list of vegetables.
In general, try to keep data sharing between controllers to a minimum. Have them refer to model objects instead to get their data.

Try using the MVC design pattern. Put all shared state information into a Model object (M of MVC) created at a higher or the top level of your app. When creating your two view controllers, give them access to the model object (by setting a property in each view controller). Then the view controllers can store and access any shared state required, and you will have it nicely centralized for debugging, storing, extensibility, reuse, etc.

Related

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.

NSFetchedResultsControllerDelegate in a second view controller (not firing?)

I am running into an issue similar to the one described here: NSFetchedResultsControllerDelegate not firing
(the delegate for my NSFetchedResultsControllerDelegate are not being called on my second view controller)
I can't seem to get the proposed solutions to work. I have a main view that loads information from Core Data just fine, but when it pushes a separate controller (and passes the managed object to it), the delegate methods won't fire. I've read about 'mergeChangesFromContextDidSaveNotification' but I don't understand how to synchronize the two manage objects and/or get the delegate methods to be called.
Any help would be greatly appreciated. Thank you,
Mike
Note sure I understand your problem exactly but a NSFetchedResultsController only calls its delegate when something changes in the part of the Core Data object graph that the controller monitors. Simply passing a managed object between two view controllers doesn't change the Core Data graph itself and therefore does not fire the the delegate methods.
To fire the delegate you have to make a change to the data that the fetchedResults controller monitors. This means changing one of entities that the fetchedResults controller fetches. You either have to add or remove an instance of an entity or you have to change an attribute or relationship of an existing entity.
...but I don't understand how to
synchronize the two manage objects
and/or get the delegate methods to be
called.
From your description, you don't have two managed objects but just one that is passed from the first view controller to the next. Perhaps you meant managed object context?
mergeChangesFromContextDidSaveNotification:
... is a method of NSManagedObjectContext and is only used when you have need to combine the data from two separate context. That is an advanced operation that you only use when you are trying to integrate the data of two independent context. For example, when you are updating a database to a new version.

iPhone: How to Pass Data Between Several Viewcontrollers in a Tabbar App

I have following problem:
I have built a tabbar application with 4 tabs. I want to pass a object/variable from the first tab controller to the third one and initialize this controller with the corresponding object.
I've already done some research. The best way, corresponding to a clean model approach, would be to call some initWithObject: method on the called viewcontroller.
How can I achieve this? How can I call the init method of the receivercontroller within the callercontroller? Can you give me some code example?
Edit:
To pass data between several views/classes etc simply create some Kind of data class which holds the data beeing shared between several classes. For more information follow the link:
Singleton
You need a data model object that stores the data for application.
A data model is a customized, standalone object accessible from anywhere in the application. The data model object knows nothing about any views or view controllers. It just stores data and the logical relationships between that data.
When different parts of the app need to write or read data, they write and read to the data model. In your case, view1 would save its data to the data model when it unloads and then view2 would read that data from the data model when it loads (or vice versa.)
In a properly designed app, no two view controllers should have access to the internal data of another controller. (The only reason a view controllers needs to know of the existence of another controller is if it has to trigger the loading of that other controller.)
The quick and dirty way to create a data model is to add attributes to the app delegate and then call the app delegate from the view controllers using:
YourAppDelegateClass *appDelegate = [[UIApplication sharedApplication] delegate];
myLocalProperty = appDelegate.someDataModelProperty;
This will work for small project but as your data grows complex, you should create a dedicated class for your data model.
Edit:
To clarify for your specific case, you would add the call to the data model when the receiver viewController becomes active.
Placing the data in an init method or a viewDidLoad won't work because in a UITabBar the users can switch back and forth without unloading the view or reinitializing the view controller.
The best place to retrieve changing data is in the viewWillAppear controller method. That way the data will be updated every time the user switches to that tab.
You might want to consider NSNotificationCenter (Reference); you register the one viewcontroller with the application notification center, and send a notification when a selection is made. When the notification is received, the other viewcontroller updates itself accordingly.
I don't think this is best practice (also check syntax) however I have got away with:
in the .h
otherclassref *otherclassname
#property (assign) otherclassname otherclassref;
and in the .m
#synthesize otherclassref;
then I just assign the reference from somewhere convenient e.g. the app delegate or wherever you are instantiating your viewcontrollers.
then the view controller can get a reference to the other view controller.
I add #class secondviewcontroller to the .h file for the firstviewcontroller and put put the #imports "secondviewcontroller.h" in the .m file of the first view controller. These are called forward references and prevent compiler errors resulting from having .h files referencing each other.