What is the best way to send data back to the root view controller before calling the popToRootViewControllerAnimated method? I am trying to signal to the rootviewcontroller that the current viewcontroller no longer exists and keep a record of what viewcontroller has been pushed thru segue.
You mustn't wait until the current view controller "no longer exists". While the current view controller does exist, the root view controller is the current view controller's navigationController.viewControllers[0]. So you have the reference you need to send a message from this one to that one. Just cast to the root view controller's class and now you can call any public method in the root view controller, e.g.
MyRootViewController* rvc = (MyRootViewController*)(self.navigationController.viewControllers[0]);
rvc.coolData = myCoolData;
There are two basic ways to do this: 1) with an NSNotification message or 2) with a delegate call. There are plenty of tutorials on how to code both. I wrote a small delegate tutorial as an answer to this question: Back button in iphone app and you can find a great NSNotification tutorial here: Send and receive messages through NSNotificationCenter in Objective-C?
You can subclass UINavigationController and override the necessary methods to track your array. I would recommend keeping a uniqued set of titles for each view controller popped off the stack. As for signaling to the current view controller that the previous view controller doesn't exist, that's what -viewWillAppear is for. If you need finer-grain control, create a protocol for your View Controller instances to conform to that the navigation controller calls out to when it pops one or more of them off the stack.
Related
On the home vc, there is a button that allows the user to select a picture. I'm wondering the better approach for when the button method is called.
Option A: Present ImagePickerController modally on the root view controller, acquire picture, and push a new view controller that deals with the picture.
Option B: Push a new vc, add ImagePicker modally onto 2nd view controller, acquire picture, and deal with the picture on that same view controller.
I would suggest following B if you have any substantive work to do with the picture before returning to the root. For two reasons:
It reduces specific code in the root Controller
If you need to do this someplace else eventually, it will be easier to reuse
Also, I would suggest having the root register itself as a delegate of the new VC and have the new VC call a delegate method when finished. It is normally the best pattern for controller reuse in a case like this.
Let's say you have an application in which you know for sure that there's always a UINavigationController displayed, and that I need to display another view controller modally from outside this controller (for example : because I use the Command pattern and I don't want to give a reference to a view controller to it).
Is there a safe way to get the "root" navigation controller, and call its presentModalViewController:animated method ?
I tried to use [UIApplication sharedApplication].keyWindow.rootViewController but I figured out that it was nil during an alert.
Are you using a storyboard or separate xibs?
If you're using separate xibs then you will be setting up the UINavigationController in applicationDidFinishLaunching.
You can make the navigation controller a property of the app delegate.
Then you can access the UINavigationController from anywhere by getting the singleton app delegate and getting the navigation controller property from it.
My application needs a notification in the view controller when I call bringSubviewToFront(). I tried viewDidAppear but it doesn't work (Obviously I shouldn't work because view is already in the stack). I have gone through the documentation of view & viewController but didn't find anything that can solve my problem. Is there any way to get view controller notified?
You won't get the viewDidAppear notification with bringSubviewToFront. It gets fired when you add the view as a subview or change the hidden property on the view. You must also make sure that your ViewController has been added as a child view controller to it's parent using
addChildViewController.
I added a custom subview to a UIViewController's content view. From that subview, how can I get a reference to the superview's controller?
Thanks
The correct answer is "You're Doing It Wrong™" ;-)
You shouldn't need to reference to a view controller from a view, and you certainly should never retain a view controller in one of your views -- or you'll end up with a retain loop and leak memory.
Cocoa provides multiple patterns to solve this problem:
Use a delegate: Define a protocol called DemoViewDelegate and add a delegate property to DemoView. Then have your view controller implement this protocol. Important: delegates should never be retained! Any delegate property you create should be set to assign. See Apple's Delegation docs or just google "delegation pattern".
Use the responder chain: Call UIApplication's sendAction:to:from:forEvent: and leave to: set to nil to have your action message automatically routed up the responder chain to your view controller. See Apple's Responder docs and the more detailed Action Messages docs.
Use a notification: Less common in this particular scenario, but you could also have your view controller listen for a notification, which the view sends.
I'm reading Apple doc but I don't understand what a root controller is. The doc says that this is the controller at the bottom of the stack. Maybe, is this the controller that I've push the first time? Anyone can explain this concept?
From Apple doc UINavigationController, I've seen that there is a method called initWithRootViewController
Initializes and returns a newly
created navigation controller.
- (id)initWithRootViewController:(UIViewController
*)rootViewController
What does it mean? Then, is it possible to change the root view controller or not?
Remember that rootViewController isn't a type of object, but a property name. It just happens to be the particular UIViewController instance at the bottom of the stack, as Nubbel said.
Methods like initWithRootViewController are for situations when you want to initialize UINavigationController, and also tell it to "use this VC as the first VC in the heirarchy".
It seems like UINavigationController really doesn't want you to change that property after it's been created, but it looks like ppl have found ways to do it: - Remember to check the comments to see if this is an "approved" method of working.
Just like the Docs and you already said, it is the controller at the bottom of the stack, the first controller pushed to the stack. Subsequent controllers will be pushed on top of the RootViewController. To return to the RootViewController you can use the popToRootViewControllerAnimated:method.
Furthermore, you can't change the RootViewController!