How to Remove a Parent View Controller in Swift - swift

There are A,B and C-View Controller.From A view controller, I used navigation push syntax to move to B.From B View Controller I used the same syntax to move to C.So that B becomes parent of C.Now I have to remove B View Controller from the stack.Can anyone suggest how to remove Parent View.When I press back button the page should redirect to A view controller From C view controller.

Use the popToViewController:animated: method provided by UINavigationController (details here)
You can get a reference to AViewController using the viewControllers property that UINavigationController provides
If your AViewController is the root vc of the nav controller, you can use the popToRootViewController:animated: method

Related

Push from one view controller to another

I have a tricky situation. The following is the hierarchy of the views that I have.
(Root)Navigation-VC-->View A-->(via Segue push)--> View B-->View C
(Root)Navigation-VC-->View A-->(via modal push)-->(Nav Controller) View D-->View E
There is a cancel button in view D. When I click on it, it correctly shows view A. But For some reasons I would want it to go to View B in the first navigation hierarchy. How can I do such transitions?
If I create a modal segue from view D to view B it destroys the navigation hierarchy that view B is part of. If I push view B from view D then view B becomes a part of a different hierarchy altogether.
Can it be done? Do I have to rethink the design?
Well, after you dismiss the modal view controller, you can always call the method performSegueWithIdentifier:sender: to push view B. Just remember to set the segue identifier in your storyboard.
Call the method dismissViewControllerAnimated:completion: in view A and call the perform segue at the completion block. This is just to avoid any corruption that might happen to the navigation controller if you dismiss and perform segue at the same time.

Dismissing a UIPopoverController from within its contentViewController?

If you want to dismiss a popover -- for example, from a button within the popover's contentViewController you must --
Create a reference to the popover to be held by view controller which creates it
Create a notification from the contentViewController to let the owning view controller know that it should be dismissed, or alternately create a delegate for the same purpose
Send the notification or delegate message when the popover is ready to be dismissed
Call dismissPopover:animated when the notification or delegate method is called
Meanwhile, from a UIViewController you can access the modal view controller, the parent view controller, the navigation controller, the split view controller, the tab bar controller, the search display controller, the child view controllers, the presenting view controllers, and the presented view controllers.
Is there a better approach to do this from popover's contentViewController?
Unfortunately, you'll have to create a weak property reference to said UIPopoverController as there's no way to access it from within the content view controller.
I was surprised how UIViewControllers can access the modal view controller, the parent view controller, the navigation controller, the split view controller, the tab bar controller, the search display controller, and as of iOS 5, the child view controllers as well as presenting and presented controllers...but not the popover controller (granted popovers aren't UIViewControllers but still).
Technically, there's a private, undocumented method to retrieve the popoverController that the UIViewController is in...I have no idea why they never made it public given that it should be exactly the same as any of the above controllers.
Though even in the private, undocumented world, there's no equivalent to dismissModalViewcontrollerAnimated:. You'll still have to get that reference then dismiss it that way.
Another way to solve this is to create an abstract view controller (for all your view controllers) that adds an NSNotification observer to a method such as -(void)closePopoverIfNecessary:(NSNotification*)notification and have child classes optionally implement the method to close their popover(s) if open. Then from within the popover's controller you fire the notification to close it. You could also pass other info via the notification (userInfo) if needed.
This way there's no need for the parent references.

Simulated "Nested" Navigation Controller in iOS

So I have a Navigation Controller in which for every row select, I push ViewController A. However, ViewController A is another table of items.
So I'm having trouble figuring out how to make ViewController A also act as a navigation controller, in which for ever row I select in ViewController A, I can push a view controller, which, we'll name ViewController B.
I tried to add a Navigation Controller object inside an existing Navigation Controller to no avail.
How will I go about this?
Thanks in advance!
NavigationController has a rootController - in your case this is a some kind of table view controller. When you push view controller A - you use parent Navigation Controller. So you can push as many as you need view controllers via this "parent" navigation controller. Read carefully this section of apple docs

Get to the view controller that pushed the visible view controller

I have an app that has a UINavigationController that pushes a UITabBarController into view. This UITabBarController has four tabs, one of which shows a custom UIViewController, an instance of EventInformationViewController. A button in this custom view controller in turn pushes another custom view controller EventRatingAddViewController into view. An action in this view controller should invoke a method in the EventInformationViewController instance. The following code makes the app crash instead:
// get the index of the visible VC on the stack
int myIindex = [self.navigationController.viewControllers indexOfObject:self.navigationController.visibleViewController];
// get a reference to the previous VC
EventInformationViewController *prevVC = (EventInformationViewController *)[self.navigationController.viewControllers objectAtIndex:myIindex - 1];
[prevVC performSelector:#selector(rateCurrentEvent:)];
I thought that the viewControllers property kept an array of all VCs on the navigation stack, so the index the currently visible one minus one should point to the VC that pushed the currently visible VC into view. Rather, it seems to point to my UITabBarController:
-[UITabBarController rateCurrentEvent:]: unrecognized selector sent to instance
What is up with that and more importantly, how do I get a pointer to the VC that pushed the currently visisble VC into view?
EDIT: I ended up creating a delegate protocol for the EventRatingAddViewController and assigning the EventInformationViewController as delegate. This works well - still I am thinking there should be a way to access the pushing VC through the navigation stack.
I'm pretty sure that that UITabBarController did indeed push your current view controller, but that what you are looking for is the view controller of one of this UITabBarController's tabs, the view controller that was visible in the UITabBarController at the time this UITabBarController pushed your view controller on the navigation stack. Possibly this UITabBarController pushed your view controller on the stack, because it was told to do so by the visible tab's view controller, so it would be something like this: [self.tabBarController.navigationController pushViewController:someViewController];.
The way to find out what view controller was shown in the UITabBarController at the time your view controller was pushed on the stack, is to use the .selectedViewController property, so that would result in something like this:
// get the index of the visible VC on the stack
int currentVCIndex = [self.navigationController.viewControllers indexOfObject:self.navigationController.topViewController];
// get a reference to the previous VC
UITabBarController *prevVC = (UITabBarController *)[self.navigationController.viewControllers objectAtIndex:currentVCIndex - 1];
// get the VC shown by the previous VC
EventInformationViewController *prevShownVC = (EventInformationViewController *)prevVC.selectedViewController;
[prevShownVC performSelector:#selector(rateCurrentEvent:)];

View controller chain

I have a Navigation Controller with a root table view which has several links. Tapping each link moves to the next view (by pushing it to the navigation controller's stack). But suppose that in that "next view", I have a UIButton that should take me further to another view (by pushing on to the same navigation controller's stack)...
View Controller-->first view-->second view-->third view..........
Now, I can easily access the Navigation Controller when I deal with the first view (and successfully push it to the Navigation Controller's stack) because it has been instantiated in the same file itself. What my real doubt is--How do you access a Navigation Controller in a far off view controller (eg, the third view or fourth view etc)? Please note that I am not using any separate delegate. All the Navigation Bar methods have been implemented in one file and connected to the Navigation Controller via an outlet.
When you push a ViewController onto a NavigationController the ViewController will automatically have it's navigationController property set. This means you can access the same NAvigationController no matter where you are in the stack.
-Update-
navigationController
In every UIViewController you can access that property.
So to in any other UIViewController that has been pushed onto the stack you should be able to just do this:
[self.navigationController pushViewController:othercontroller animated:YES];
Look at the documentation for UIViewController to see what other magic properties you have available.