iphone: send back string value with navigationcontroller pop - iphone

This may be very basic, but I just can`t figure out what to do, so thanks for any response...
I`m using a navigationcontroller and are currently on the second level in the stack. Here i set a string value and use popViewControllerAnimated to go back to first level in the stack.
What might be the best solution to use that string value from second level in the stack? I`ve tried to set a value in the first level manually in the second level, but I must be doing something wrong...
Thanks!
edit: Im very new to both objective-c and C in general so im still a bit confused :(

Consider applying MVC pattern in your program - store the string value in a separate globally accessible storage class (in simple cases you can use application delegate or create a singleton object for this purpose). Then in your 2nd level controller you set the value in the storage and in 1st level you get it from the storage.

Would it not be better to use a delegate pattern? You could define your top-level view as a delegate of the second-level view; you set the delegate property of the second-level controller before pushing it on the stack.
Once the string has been selected, before popping the second-level controller, call the delegate method with the string as its argument.
The advantage of that would be that it'd still work even if you have multiple instances of the same 2nd level controller (eg in a tabbed interface).

It's not the best solution, but it works:
[[self.navigationController.viewControllers objectAtIndex:0] setSmt:#"123"];
[self.navigationController popViewControllerAnimated:YES];
The value "smt" in the parent view controller will change.

Related

How to pass data from child to second parent view controller without using NotificationCenter in swift

My situation is, I have a navigation controller(nv) with root view controller(rootVC). And another view controller(firstChildVC) pushed to rootVC. And one more view controller(secondChildVC) pushed to firstChildVC. (In real case, I have more subsequence child view controllers) After API calls and some calculations in secondChildVC, I need to pass some data from secondChildVC back to rootVC and popToRootViewController to show some data.
I don't think delegate and closures are good choice in this case. The only thing I could come up with is using NotificationCenter. Just what to know is there any better way to do this?
Thank you in advance.
You can try this inside the SecondVC then pop to root
if let root = self.navigationController?.viewControllers.first as? RootVC {
root.sendData(data)
}
I think there are three valid ways to do this without overly tightly coupling things:
Notification Center
Closures
Delegate pattern
The right way is not a simple choice. It really depends on the details. You mention making an API call. Assuming this is all managed in a separate object and not coded into your view controller code, I would have the object making the API call post a notification and the view controllers can each listen and do whatever is appropriate.
There are two other ways to do this, one is using Delegates another one is Closures

How to set the delegate to another ViewController?

I've recently started developing for the iPhone and so far I'm doing pretty good but there's this basic pattern I really don't seem to get.
Say, I have a TabBar with two views and a custom delegate protocol, thus my structure is the following:
AppDelegate.h/.m
myDelegateProtocol.h
FirstViewController.h/.m
SecondViewController.h/.m
MainView.xib
FirstView.xib
SecondView.xib
Now I want to achieve the following: I placed a button in the FirstView.xib and I'd like the IBAction which it invokes (inside FirstViewController ofc.) to send a message to the SecondViewController ([self.delegate tellSecondViewContrToSayHi]) and invoke another method which simply prints a log into the console saying "hi I'm here."
So far I know what I need to do in theory:
Specify the protocol.
Implement the protocol in the SecondViewController.
Create an id< myDelegateProtocol > delegate inside my FirstViewController,...AND last but not least:
Set the self.delegate = secondViewControllerObject.
Now, nr.4 is where the problem's at. How on earth do I link the delegate to the other viewController? I mean I'm not the one instantiating the views as the tabBar kinda does that for me,... any advise? Or am I just way too tired to notice a really stupid thing I did somewhere?
Theoretically the same question also applies to the target:action: thing,... I mean, how do I define the target?
Thanks a lot,
wasabi
You have the right idea, assuming that you want relatively tight coupling between these controllers via that delegate protocol.
Since neither controller knows about the other until that delegate property is set you need to have some object which has a reference to both of them wire up that relationship. In your case that's probably the application delegate which can create both controllers, set one as the delegate of the other, and pass both along to your tab bar controller.
What you might actually want is to have the app delegate give both controllers a reference to some shared model object. Your FirstViewController can update that model when you tap a button and your SecondViewController can observe changes to the model to update it's display (or just update its view when it appears based on the current model state). That way your controllers don't need to know anything about each other.

Calling NSXMLParser based on navigation direction

I have an navigation-based app with three view controllers. The first has categories of information, the second has a list of items from that category and the third has detail on a specific item.
I populate view controllers 1 and 2 using an NSXMLParser which gets called on viewWillAppear. In the forward (VC1 to VC2 to VC3) direction, everything is fine, the parser gets called and the views are populated.
Unfortunately when the user chooses the back button on the navigation bar, the same process happens in reverse (VC3 to VC2 to VC1) as viewWillAppear is called again and so the parser is also called, even though it just fetches the same data.
I want to ensure that the parser is only called in the forward direction. Any ideas how I might structure this?
Thanks, Phil
Could you do something as simple as having a BOOL ivar called goingForward on VC2 that gets set to YES by VC1 prior to -pushViewController:animated: call and set to NO by VC3 prior to -popViewControllerAnimated: ... and then check goingForward in VC2's -viewWillAppear?
I am sure that there are more elegant ways of doing this (and look forward to reading about them) - but this should work, don't you think?

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 )

How do I access the managedObjectContext from a controller deep in the UI?

I'm still a little fuzzy on understanding iPhone/Cocoa in general so this is probably a simple question.
I have a CoreData Window-Based App for the iPhone. The rootController is a UITabBarController. The first tab view has a UINavigationController attached to it with a table in it's main view.
When the App starts the objectContext is set up, which makes sense to have the App do that once. But now I have the managedObjectContext in the main Controller but I want to get that passed down to the Controller of the View inside the navcontroller, inside the first item in the TabBarController's tab list. How do I do this?
Would naming the one of the fields in the UI Inspector Tool allow me to do something like:
tabcontroller.navcontroller.manageObjectContext = self.managedObjectContext;
Would this only work if the controller was instantiated and 'live'. (Do the controllers not get instantiated until they are needed?) What if this was in a view that was for the most part hidden?
Anyway this is probably a simple thing I'm just not understanding things properly yet.
What is the general right way to share the manageObjectContext that is created and setup in the rootController to the many sub-controllers in the app?
I'm guessing this is the preferred method assuming the core-data initialization is done in the AppDelegate:
[[[UIApplication sharedApplication] delegate] managedObjectContext]
I usually give controllers a - (id)initWithManagedObjectContext:(NSManagedObjectContext *)context init method and a corresponding variable.
If a controller creates another controller in turn, it will, if needed, pass the NSManagedObjectContext to that controller in the same manner.
If you don't want to create an extra init method, just give the controllers a property for the NSManagedObjectContext and set that property directly after creating them.
I usually try to limit the number of controllers that directly deal with and "know about" Core Data though.
The answers to this question provide several means of accessing the Core Data stack deep within your application. As I indicate in one of the comments, I prefer to use a singleton DatabaseController that can be accessed from wherever, similar to how the NSUserDefaults' standardUserDefaults works.