How to access the topmost UINavigationController - ios

I have displayed two NavigationControllers in my iOS app. I need to access the topmost NavigationController programmatically. I tried
[UIApplication sharedApplication].keyWindow.rootViewController
but it returns the bottom NavigationController. How could I access the UINavigationController which is on the top using Objective-C?

you can use PresentingViewController property of the bottom navigation controller to reach to it's displaying controller, and then use the navigationController of the said controller.
something like this:
[[bottomNavController presentingViewController] navigationController]
but I strongly suggest that instead of this approach you walk up trough all your presenting controllers and find the last navigation controller that exists in the chain.
Cheers

Related

presentViewController with the tabbar

I have a app which has a tabbar which is presented in most of the ViewControllers. The problem is its not showing in an viewController which i'm presenting by this code.
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:songsViewController];
[self presentViewController:navigationController animated:YES completion:nil]
I'm using the presentViewController instead of the pushViewcontroller, cause i want to customize the navigationBar in this view.
How can i present my standard tabbar which i've created using storyboard?
When you use presentViewController:animated:completion, you are presenting the view controller modally, meaning it is not being contained within any of your existing containers like a UITabBarController or anything like that. So if you want something to show up when you present a UIViewController modally, it must be contained within the view controller that you're modally presenting. So from the looks of it, you're simply presenting a UINavigationController with your songsViewController contained within it. If you want to keep your UITabBar showing, either you need to add one to the view you're presenting, or you need to change your code so that you're not presenting a view controller modally here. And to add a second UITabBar for the modal view that matches the UITabBar that you were already presenting, it will make your app work rather strangely, so I would suggest trying to change it so you're not having to present a modal view at all.

iOS Storyboards - Re-use UIViewController

I've got the following structure setup in my Storyboard.
I've got a TabViewController (circled in red) that shows a UIViewController via one of its tabs by doing a push (circled in blue).
I want to re-use that UIViewController from the TabViewController. I'd like to 'push' it but I don't really have a navigation controller so I may end up displaying it as a modal.
However, I'm not sure how to handle navigation back to the TabViewController since in this case there's no navigation bar. Any suggestions on the best way to handle this?
EDIT
Is there a way to insert a Navigation controller when its displayed directly from the TabViewController?
Why don't you put your view hierarchy like this:
UITabBarController -> UINavigationController -> BlueViewController
This UINavigationController should be put in the viewControllers property of the UITabBarController instance. If you do this, you can push and pop as many view controller as you want and you can also hide the navigation bar if needed.
Cancel button whose action is [self dismissViewControllerAnimated:YES completion:nil];

difference between presentViewController and UINavigationController?

Please tell the difference between presentViewController and UiNavigationController? Could I use presentViewController instead of UINavigationController to navigate different views in the app?
Whats the scenario to use either?
presentViewController offers a mechanism to display a so-called modal view controller; i.e., a view controller that will take full control of your UI by being superimposed on top of a presenting controller.
UINavigationController offers a much more flexible mechanism where you can push a new controller, and later pop it, so to go back to the previous one, in a ordered way. Imagine that controllers in a navigation controller will just build a sequence from left to right.
I think that presentViewController is most suitable for use with just one view controller being presented at a time. You can surely use it to stack more view controllers one on top of the other (and thus sort of "mimic" a poor-man's navigation controller), but my bet is you will quickly find something not working as you expected.
Specifically, an example of such limitation is the following: when you dismiss a modal view controller (in order to "close" it), all of your modally presented view controllers (from the same presenting controller) will also be dismissed at once. So you simply will not be able to implement a "go back"/navigation like functionality.
So, it depends on what you are trying to do.
A UINavigationController is a subclass of UIViewController that manages a stack of view controllers and adds a back button etc.
presentViewController is a method of the UIViewController class you use to present a modal view controller.
The UINavigationController maintains a navigation stack for you. You are then able to navigate through hierarchical content.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UINavigationController_Class/Reference/Reference.html
If you use UIViewControllers presentViewController method you are basically just replacing the view controller. no navigation stack is maintained for you.
UINavigationController is a class, presentViewController is an instance method of UIViewController (iOS 5 + ), of which UINavigationController is a subclass.
pushViewController is a comparable method to presentViewController. It is an instance method of UINavigationController, for iOS 2 +

How to show modalviewcontroller above tabbar

I have tab bar and in view "A" and in "A" I have navigation controller. SO inside my navigation controller in "A" i called
[self presentModalViewController:modalView animated:YES]
But modalView shows under tab bar. How to show it above tab bar?
Try to present modal view from UITabBarController:
[self.tabBarController presentModalViewController:modalView animated:YES];
My case, the modal has a transparent background, I set modalPresentationStyle is .overFullScreen and it show at above tabbar with clear background.
In my case the presented view controller had UIModalPresentationStyle.CurrentContext at .modalPresentationStyle, which made the tab bar overlap
Jus switch back to a default value to fix the issue
The cause of this is that the ancestor viewController is not correctly set.
for instance imagine:
UIViewController * myController = ... // a view controller without a proper ancestor
now:
myController.tabBarController == nil
Therefore:
[myController presentModalViewController:otherController];
Will fail (by showing up under the tab bar). The fix is to add myController to its ancestor via
[parentController addChildViewController:myController];
Now, parentController must be added to another controller in the same way and so forth until the root one is your tabController. This is only available in iOS 5+. If build for iOS 4 or earlier, you will have to work around this by making sure all of your controllers are directly added to either a UINav or UITab controller. If this is not possible, you will have to access the UITabBarController via a global variable.

pushViewController without navigationcontroller

I have a class that is of type UITableViewController.
This class has a member of type UINavigationBar that I use for adding in an edit button for the table view.
Using this method calling is invalid.
[self.navigationController pushViewController:controller];
How can I push a detail view onto the view after selecting a table row without wrapping my UITableViewController in a UINavigationController?
The closest alternative if you don't want to use navigation controller are modal view controllers.
[self presentViewController:controller animated:YES completion:nil];
This will slide the controller into your screen from bottom, or if you change controller's modalTransitionStyle it can flip over or fade in.
To dismiss the controller just call:
[self dismissViewControllerAnimated:YES completion:nil];
I would wrap the UITableView inside a UINavigationController and just hide the UINavigationBar.
[self.navigationController setNavigationBarHidden:YES animated:NO];
And then create a back button that pops the ViewController off the stack.
[self.navigationController popViewControllerAnimated:YES]
What could also be done is to use a Navigation Controller as usual and then hide it.
To hide the Navigation Controller using storyboards: select it and uncheck "Show Navigation Bar" in the attribute inspector. Others might suggest to hide the navigation bar in each controller, but the problem with that is that it will appear for a millisecond and then disappear.
You can't push a view controller onto a navigation controller if there is no navigation controller. If you are wanting to be pushing controllers and have it display the topmost controller and everything, just use a UINavigationController and be done with it.
You can push arbitrary UINavigationItems onto your UINavigationBar, and your bar's delegate will be notified when the user uses the back button so you can take appropriate action. See the documentation for more information.
It's true that without a UINavigationController you can not push view controllers. You rather present view controllers modally via UIViewController.present(_ viewControllerToPresent:, animated:, completion:)
But it's possible to create a custom segue to display the view controller as if it were a push (or any other animation you want), although it seems that using a UINavigationController just makes things easier.
Here are some related links to the documentation:
UINavigationController Class Reference
Customizing the Transition Animations
Presenting a Modal View Controller

Resources