I use iOS5 storyboard, and my initial view controller is TabBarController, there are four relationships to view1 & view2 & view3 & view4, so, how can I get the view3's view controller?
I tried:
[[[[self.window.rootViewController navigationController] tabBarController] viewControllers] objectAtIndex:2];
But it doesn't work...
You said that your initial (root) view controller is a UITabBarController but you are referring to a view controller with a navigation controller with a tab bar controller. Are you getting mixed up in your view controller hierarchy?
edit:
if your root view controller is actually just a tab bar controller and you want to get the 3rd tab here is the code:
[[((UITabBarController *)self.window.rootViewController) viewControllers] objectAtIndex:2];
[self.tabBarController setSelectedIndex:2];
Try this way
In any view controller
YourViewController *yourViewController= (YourViewController*) [self.tabBarController.viewControllers objectAtIndex:3];
this return your that view controller object.Cast it to your view controller and you are ready to use that.
run and Go
Swift 4.0
let viewC = self?.tabBarController.viewControllers.first // will give single Navigation Controller on index 0
let viewC = self?.tabBarController?.viewControllers// will give array of Navigation Controller
Further you can check the Visible ViewController
if let nav = viewC as? UINavigationController {
if nav.visibleViewController is YourViewControllerName{
// Do Code
}
}
UIViewController *loginViewController=self.window.rootViewController;
UITabBarController *controller=loginViewController.tabBarControllerObj;
UIViewController *selectedController=controller.selectedViewController;
From this you will get selected view controller.
For getting all view controller just replace
NSArray *viewControllers = [controller viewControllers];
Related
I'm loading a table view control by pressing a button in view controller
.The code in my Viewcontroller.m is
-(IBAction)go:(id)sender{
TableViewController *sec=[[TableViewController alloc]init];
sec.modalTransitionStyle=UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:sec animated:YES];
}
Now my table view controller loads..Now i need to add a navigation bar which have title and back button which loads view controller.I also want to know how to assign action to that back button where i can load view controller
I tried out in google which all makes tableviewcontroller as root view controller where in my app rootviewcontroller is view controller..Is there a way to add that in my xib or by programmatically.
Help pls..
You can do this:
-(IBAction)go:(id)sender{
TableViewController *sec=[[TableViewController alloc]init];
UINavgationController *nav = [[UINavgationController alloc] initWithRootViewController:sec];
nav.modalTransitionStyle=UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:nav animated:YES];
}
I am using popToViewController method to pop to a view controller. What I was trying to achieve is to pop to an UITabBarController's specific index.
NSArray *viewArrays = [self.navigationController viewControllers];
So my view hierarchy is;
<LoginViewController: 0x6b75850>,
<UITabBarController: 0x6ba0b50>,
<RequestViewController: 0x684fe90>,
<ApplyViewController: 0x6845790>
Following code does pops to my UITabBarController, but since I was on the third view of my UITabBarController, it pops back to the third view
[[self navigationController] popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
What I want is to pop to the second view of my UITabBarController.
Edit (Answer)
As stated, we don't push or pop. So in order to gather your tabBarController you either use;
UITabBarController *myTabController = [self.navigationController.viewControllers objectAtIndex:indexOfYourTabBarControllerInYourNavigationController];
myTabController.selectedIndex = indexToGo;
or if you are on one of your tabBarController views;
self.tabBarController.selectedIndex = indexToGo;
In UITabBarController you dont pop and push, if you want to go to the second view you would set the selected index instead
Like so
yourTabController.selectedIndex = 1;
Or if the current view controller is a part of the tabBarController do
self.tabBarController.selectedIndex = 1;
This is what I am doing. I have a tabBarControllerOne with 5 tabs. On clicking one of the tabs, I present a modal view controller, which has a navigationBar and a TabBarControllerTwo (with 3 tabs). These three tabs are the matter for concern here.
In the 5th Tab of tabBarController I show modalViewController as
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.nextTabView];
// navController.navigationBarHidden = YES;
navController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
NSLog(#"Displauing the navcontroller before pushing %#", navController);
[self presentModalViewController:navController animated:NO];
Here, nextTabView is a tabBarController with 3 tabs. The views work. In the views, if I try something like.
self.navigationController.navigationBarHidden = YES;
[self.navigationController pushViewController: someController animated:YES];
// nothing works.
If I NSLog, it displays self.navigationController as (null)
Can someone tell me why this is not working ?
Embedding a UITabBarController inside a UINavigationController is not supported. Apple has a careful hierarchy of container view controllers, and a UITabBarController must be the root of its view controller hierarchy.
Additionally, as Joe points out, your views don't belong to the navigation controller; they belong to the tab bar controller, so their navigationController property is not set.
The modal view controller does not belong to a UINavigationController stack therefore the property is not set. You will want to use delegation to notify the creating controller when something is selected then that controller can properly push the next controller on to the stack.
UIViewController Reference:
Discussion
Only returns a navigation controller if the view controller
is in its stack. This property is nil if a navigation controller
cannot be found.
How to install a NavigationController as the root view in a tab bar view?
In my applicaton:didFinishLaunchingWithOptions: method I created a tab bar interface, setting the rootViewController of the window as the tabBarController.
Now, in one of my tab bar views, I want to add a navigation bar at the top. How can I accomplish this?
Should I subclass navigationcontroller?
Thanks
It sounds like you're doing it in code, not IB, so here's what you can do.
// First create your RootViewController:
UIViewController *rootViewController = [[UIViewController alloc] init];
// Then add the rootViewController to a UINavigationController
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
// Now your RootViewController is a UINavigationController
// Add it to your UITabBarController
[tabBarController.viewControllers addObject:navigationController];
// You can now get rid of the RootViewController and UINavigationController
[rootViewController release];
[navigationController release];
You can do this in the Interface Builder. Replace the view controller inside the tab bar controller with a navigation controller. Then set the class and Nib name of the view controller (inside the navigation controller) to your root class.
You have to first create a UITabbarController application, then go to MainWindow.xib file. By default two tab view will be created.
Check the attribute property of the tab bar and change the view to RootViewController. You will have to set the class name and xib file name to RootViewController.
I am showing a modal view which is a UITableViewController class. For some reason it won't show the navigation bar when I show it. Here is my code:
SettingsCreateAccount *detailViewController = [[SettingsCreateAccount alloc] initWithStyle:UITableViewStyleGrouped];
detailViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
detailViewController.navigationController.navigationBarHidden = NO;
[self.navigationController presentModalViewController:detailViewController animated:YES];
detailViewController = nil;
[detailViewController release];
I thought it was shown by default? If it helps, I am calling this from another class that is also a UITableViewController managed by a UINavigationController. Ideas?
When you present a modal view controller it does not use any existing navigation controllers or navigation bars. If all you want is to display a navigation bar, you need to add the navigation bar as a subview of your modal view and present it as you're doing.
If you want to present a modal view controller with navigation functionality, you need to present a modal navigation controller containing your detail view controller instead, like so:
SettingsCreateAccount *detailViewController = [[SettingsCreateAccount alloc] initWithStyle:UITableViewStyleGrouped];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
[detailViewController release];
navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:navController animated:YES];
[navController release];
Your modal controller will manage its own navigation stack.
Here is one way to display navigation bar for those who are using storyboards, suggested by Apple's Tutorial on Storyboard.
Because a modal view controller doesn’t get added to the navigation stack, it doesn’t get a navigation bar from the table view controller’s navigation controller. To give the view controller a navigation bar when presented modally, embed it in its own navigation controller.
In the outline view, select View Controller.
With the view controller selected, choose Editor > Embed In > Navigation Controller.
On iOS 7 and you just want a navigation bar on your modal view controller to show a title and some buttons? Try this magic in your UITableViewController:
// in the .h
#property (strong) UINavigationBar* navigationBar;
//in the .m
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title = #"Awesome";
self.navigationBar = [[UINavigationBar alloc] initWithFrame:CGRectZero];
[self.view addSubview:_navigationBar];
[self.navigationBar pushNavigationItem:self.navigationItem animated:NO];
}
-(void)layoutNavigationBar{
self.navigationBar.frame = CGRectMake(0, self.tableView.contentOffset.y, self.tableView.frame.size.width, self.topLayoutGuide.length + 44);
self.tableView.contentInset = UIEdgeInsetsMake(self.navigationBar.frame.size.height, 0, 0, 0);
}
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
//no need to call super
[self layoutNavigationBar];
}
-(void)viewDidLayoutSubviews{
[super viewDidLayoutSubviews];
[self layoutNavigationBar];
}
I want to share how the accepted solution can be used in projects with storyboards:
The simple approach is to put in a storyboard blank navigation controller before the VC which is to be presented modally, so the relations look like:
(Presenter VC) -> presents modally -> (navigation controller having a controller to be presented as its root).
We've tried this approach for a while and noticed that our storyboards become "polluted" by a large number of such intermediate navigation controllers when each! of them is used exclusively for one! presentation of some other controller, that we want to be presented modally with navigation bar.
Our current solution is to encapsulate the code from accepted answer to a custom segue:
#import "ModalPresentationWithNavigationBarSegue.h"
#implementation ModalPresentationWithNavigationBarSegue
- (void)perform {
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:self.destinationViewController];
[self.sourceViewController presentViewController:navigationController animated:YES completion:nil];
}
#end
Having this segue in our project we do not create intermediate navigation controllers in our storyboards anymore, we just use this ModalPresentationWithNavigationBarSegue like:
Presenter VC --> Presentee VC
I hope that this answer will be helpful to people who like to avoid unnecessary duplication in their apps storyboards.
I just wanted to add something to what #Scott said. His answer is definitely the easiest and most accepted way of doing it now with Storyboards, iOS 7 and 8... (and soon, 9).
Definitely adding a view controller to the Storyboard and Embedding it as described by #Scott is the right way to go.
Then, just add the segue by control-dragging from the source view controller to the target (the one you want to show modally), select "Present Modally" when the little view appears with the choices for the type of segue. Probably good to give it a name too (in the example below I use "presentMyModalViewController").
One thing that I needed that was missing is #Scott's case is when you want to actually pass on some data to that modally-presented view controller that is embedded in the navigation controller.
If you grab the segue.destinationViewController, it will be a UINavigationController, not the controller you embedded in the UINavigationController.
So, to get at the embedded view controller inside the navigation controller, here's what I did:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"presentMyModalViewController"]) {
// This could be collapsed, but it's a little easier to see
// what's going on written out this way.
// First get the destination view controller, which will be a UINavigationController
UINavigationController *nvc = (UINavigationController *)segue.destinationViewController;
// To get the view controller we're interested in, grab the navigation controller's "topViewController" property
MyModalViewController *vc = (EmailReceiptViewController *)[nvc topViewController];
// Now that we have the reference to our view controller, we can set its properties here:
vc.myAwesomeProperty = #"awesome!";
}
}
Hope this helps!
If you only need a NavigationBar, you can add an instance of UINavigationBar and assign BarItems to it.