Navigation Controller with TabBarController in App - ios

I am trying to make a tableview with two views, the tableview controller and the otherView controller. The tableview needs a navigation controller to get to a third view when a cell is clicked. I tried using the code below in my AppDelegate.m but it just creates the tableview with the navigation controller. Any suggestions on how I should edit this to get the tabview working as well? Thanks!
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
AJBTableViewController *masterViewController = [[AJBTableViewController alloc] initWithNibName:nil bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
_mainTabBar.viewControllers = [NSArray arrayWithObjects:_navigationController, otherViewController, nil];
[_window addSubview:_mainTabBar.view];
return YES;
}

The tab bar controller should be the root view controller of the app, not the navigation controller of the first tab bar item.

_mainTabBar.viewControllers = [NSArray arrayWithObjects:_navigationController, otherViewController, nil];
[_window addSubview:_mainTabBar.view];
Instead this code, you try below code:
UITabBarController *tbC = [[UITabBarController alloc]init];
tbC.viewControllers = [NSArray arrayWithObjects:_navigationController,otherViewController, nil];
self.window.rootViewController = tbC;
and delete
self.window.rootViewController = self.navigationController;

Sorry for the stupid error, I never allocated an instance of the tabbar controller, Mundi is right, making the rootviewcontroller the tabbarcontroller is the way to go.

Related

Setting UINavigationController (from storyboard) as rootViewController in AppDelegate.m

I'm using parse and I'm trying to get the login screen to show if the user isn't the "current" user. I'm having issues with my NavigationController (from my storyboard) and using it as the rootViewController even though it's already set as initial View Controller in my storyboard. Using this line of code I select the NavigationController (from my storyboard) and initialize it in my app delegate.
UINavigationController *navVC = (UINavigationController *)self.window.rootViewController;
I then decide whether or not to display the loginVC then finally I set the NavigationController as the rootViewController here:
self.window.rootViewController = navVC; [self.window makeKeyAndVisible];
Except someone I don't. I get this error when I try to build my app. "Application windows are expected to have a root view controller at the end of application launch" Anyone have any ideas what's going wrong?
Here's the code all together.
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
UINavigationController *navVC = (UINavigationController *)self.window.rootViewController;
// Initialize Parse.
[User registerSubclass];
[Question registerSubclass];
[Parse setApplicationId:#"HI"
clientKey:#"HI"];
// Determine whether or not to show the login screen
if (![PFUser currentUser]) {
LogInViewController *loginVC = [[LogInViewController alloc] init];
[navVC setViewControllers:#[loginVC] animated:YES];
} else {
QuestionsTableViewController *questionsVC = [[QuestionsTableViewController alloc] init];
[navVC setViewControllers:#[questionsVC] animated:YES];
}
self.window.rootViewController = navVC; [self.window makeKeyAndVisible];
return YES;
}
If you're starting with a storyboard you need to have it set as your Main Interface in the Deployment Info in your app's General settings. You should also remove the line:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
..as it's initialising a new window in the place of the one created from the previous step.
I used these two lines of code to fix the issue. I got answer from here:
Programmatically set the initial view controller using Storyboards
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController *navVC = [storyboard instantiateViewControllerWithIdentifier:#"QuestionsView"];
I removed this line:
UINavigationController *navVC = (UINavigationController *)self.window.rootViewController;
There don't get the error anymore.

Retaining the same tab bar in a new view

I am a newbie with regards to IOS Development, so I really need help regarding this matter. I have been working in a program where in a have a slide bar as well as a tab bar. However, when I click an item from the slide bar, it goes to the new view and the tab bar disappears. I tried embedding the new view into a navigation controller and adding a push segue between my tab bar controller a to the new view.. but still, tab bar won't show up.
What will I do to retain or use my existing tab bar in my new view? so, it will be visible to the new view.
Thanks! your help is very much appreciated. :)
First, you gotta perform a push, not a modal. Then, you could use this method hidesbotTombarWhenPushed in the view controller that pushes, that should do the trick.
If not, maybe you can clarify more or post some code :)
This may be because of you are not adding tabview controller as the window's root view controller in AppDelegate. Check the sample code below
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
searchController = [[SearchController alloc]initWithNibName:#"SearchController" bundle:nil];
navCtrl1 = [[UINavigationController alloc]initWithRootViewController:viewController];
navCtrl2 = [[UINavigationController alloc]initWithRootViewController:searchController];
NSMutableArray *viewControllersArray = [[NSMutableArray alloc]init];
[viewControllersArray addObject:navCtrl1];
[viewControllersArray addObject:navCtrl2];
tabController = [[UITabBarController alloc]init];
tabController.viewControllers = [NSArray arrayWithObjects: navCtrl1 ,navCtrl2,nil];
self.window.rootViewController = tabController;
[self.window makeKeyAndVisible];
return YES;
}

Can [self.window makeKeyAndVisible]; be called before setting rootviewcontroller

My requirement is that UITabBarController is the rootviewcontroller and on very first time of app launch I want to show login procedure which is inside UINavCon, and I am displaying it through presentViewController.
I dont want the UITabBarController visible for first time and dont want to how login UINavCon popping as modal.
I want to make user experience that if app starts for first time login UINavCon should be visible. So here is my code:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window makeKeyAndVisible];//is it correct to call it here?
LoginVC *loginObj = [[LoginVC alloc]init];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:cellPhoneNumber];
self.tabBarController = [[UITabBarController alloc]init];
self.window.rootViewController = self.tabBarController;
[self.tabBarController presentViewController:self.navigationController animated:NO completion:^{}];
return YES;
}
I am calling [self.window makeKeyAndVisible]; on second line right after uiwindow alloc init. Is it correct do this or I can experience problems like viewcontroller not receiving events or orientations notifications?
you can call it whenever you want. Calling it affects the window's z-index and screen property.
it doesnt depend on any specific content being set.
You haven't mentioned that whether you got the code working or not by using your implementation. Anyways I have done similar kind of implementation recently where we need to present login controller and then tabBarController after logging in, so just sharing my implementation.
Create your login controller and present it in didFinishLaunching method.
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
LoginController *loginCObj= [[[MainScreenController alloc]init]autorelease];
UINavigationController *navigationControllerObj = [[[UINavigationController alloc]initWithRootViewController:loginObj]autorelease];
self.window.rootViewController = navigationControllerObj;
[self.window makeKeyAndVisible];
After that on succesful login in your login view controller, call an appDelegate public method
In login controller
AppDelegate *appDel = (AppDelegate *)[[UIApplication sharedApplication] delegate];
[appDel applicationLoggedInSuccesfully];
In your appDelegate file, add a method like this:
-(void)applicationLoggedInSuccesfully{
UINavigationController *nv1 = [[[UINavigationController alloc] initWithNibName:nil bundle:nil]autorelease];
TabController1 *v1 = [[[TabController1 alloc] initWithNibName:nil bundle:nil]autorelease];
[nv1 pushViewController:v1 animated:NO];
UITabBarController *tabController = [[[UITabBarController alloc] init]autorelease];
tabController.viewControllers = #[nv1];
tabController.delegate = self;
self.window.rootViewController = tabController;
[self.window makeKeyAndVisible];
}
Hope it will help you.

Tabbed application won't show Login view

I have a tab bar application in Xcode 4.3 and I'm trying to insert a login screen before the tabbar is shown. The app works OK if presentModalViewController has animated:YESbut if it is without animation the view is not showing.
#synthesize window = _window;
#synthesize tabBarController = _tabBarController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController *viewController1 = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
UIViewController *viewController2 = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
self.tabBarController = [[UITabBarController alloc] init];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
self.window.rootViewController = self.tabBarController;
LogInViewController *logViewController = [[LogInViewController alloc] initWithNibName:#"LogInViewController" bundle:nil];
[self.window addSubview:_tabBarController.view];
[self.tabBarController presentModalViewController:logViewController animated:YES];
//This wont work
//[self.tabBarController presentModalViewController:logViewController animated:NO];
[self.window makeKeyAndVisible];
return YES;
}
-(void)loginDone{
NSLog(#"back to the app delegate");
[self.tabBarController dismissModalViewControllerAnimated:YES];
}
Is this the right way to do it?
Why wont the code work with animated:NO ?
I also get this on output Unbalanced calls to begin/end appearance transitions for <UITabBarController: 0x689d350>.
First of all, move [self.window makeKeyAndVisible]; before your view controller setup.
Additionally, you should be presenting the modal view controller within the viewWillAppear: method of the view controller that will be visible first, to make sure your apps view hierarchy has been fully initialized before presenting your login screen.
Don't do this:
[self.window addSubview:_tabBarController.view];
Do this:
self.window.rootViewController = _tabBarController;
This will put the tabBarController on the screen. But that's not exactly what you want... My advise is:
1) Start by putting the logViewController has the rootViewController as I showed you above.
2) Once you got what you want (login is successful) just tell the AppDelegate to switch the rootViewController. This can be done in with delegation or notifications.
Also, as Toastor indirectly pointed out, you should start the presentViewController from the UIViewController who actually initiates it (and not from the AppDelegate).

Using a navigationcontoller with a tabbar controller

I'm trying to make it so I have a tab bar at the bottom of my screen, and it's always there. I also want it so if I "click" into some menu in one of the tabs, it gives you the option to go back, thus a navigation controller and a tab bar controller.
I still don't really understand iOS, so the answer I found is confusing me.
This Answer: Having a UITabBar AND a UINavigationController in an app?
So how do I implement this? I'm guessing I change this method in my App Delegate,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
UIViewController *viewController1, *viewController2;
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
viewController1 = [[CFSDFirstViewController alloc] initWithNibName:#"CFSDFirstViewController_iPhone" bundle:nil];
viewController2 = [[CFSDSecondViewController alloc] initWithNibName:#"CFSDSecondViewController_iPhone" bundle:nil];
} else {
viewController1 = [[CFSDFirstViewController alloc] initWithNibName:#"CFSDFirstViewController_iPad" bundle:nil];
viewController2 = [[CFSDSecondViewController alloc] initWithNibName:#"CFSDSecondViewController_iPad" bundle:nil];
}
self.tabBarController = [[UITabBarController alloc] init];
[self.tabBarController setDelegate:self];
self.tabBarController.viewControllers = [NSArray arrayWithObjects:viewController1, viewController2, nil];
self.window.rootViewController = self.tabBarController;
[self.window makeKeyAndVisible];
return YES;
}
Thanks for your assistance!
First of all you don't need to to manually set up the nib name. You could just name them CFSDFirstViewController~iphone.xib and CFSDFirstViewController~ipad.xib. Then you can call [[CFSDFirstViewController alloc] init] and let iOS do the rest for you. For info see iOS Supports Device-Specific Resources.
About your question, you can only insert the UINavigationController within the UITabBarController. To do it wrap viewController1 within a UINavigationController like the following:
CFSDFirstViewController viewController1 = [[CFSDFirstViewController alloc] init];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:viewController1];
and then use navController instead of viewController1 like the folliwing
self.tabBarController.viewControllers = [NSArray arrayWithObjects:navController, nil];
Check the code because I wrote by hand. And pay attention to memory if you use a non-ARC project.
Hope it helps.

Resources