I'm working on a project that started out as a TabBarController-based app, and still mostly is, but some requirements have changed and we need to put in an initial view controller as an entry point to the rest of the app - one that will, after authentication is given and some things are loaded, will be replaced in the main window by the tab bar controller.
The original UITabBarController was a component of MainWindow.xib, and had all its root navigation controllers set up with root view controllers, and everything was going fine. I figured I could simply extract that UITabBarController component from the MainWindow.xib, put it in its own CustomTabBarController.xib, and then run
[self setTabBarController:[[[UITabBarController alloc] initWithNibName:#"CustomTabBarController" bundle:nil] autorelease]];
[_tabBarController setDelegate:self];
[self.window addSubview:_tabBarController.view];
However, instead of getting the pre-built tab bar controller I expected, I get a completely empty tab bar controller.
Am I missing something? Why can't I load a pre-built UITabBarController from a nib?
Try this instead:
NSArray *nibContents = [[NSBundle mainBundle] loadNibNamed:#"CustomTabBarController" owner:nil options:nil];
UITabBarController *controller = [nibContents objectAtIndex:0];
[self setTabBarController:controller];
[_tabBarController setDelegate:self];
[self.window addSubview:_tabBarController.view];
It's kind of tricky to explain why, but it's to do with how file's owner works. If the tab bar controller is defined in the nib file, you can't load the nib file into a tab bar controller.
Nibs always have to be loaded by an object one level above the object defined in the nib - so an app delegate can load a view controller, a view controller can load a view, etc. But a view controller (including a TabBarController) can't load itself.
Related
I just inherited a project that uses a Storyboard + nibs.
The Storyboard had a navigation controller set as the initial view controller, and then had the first view controller set as its root. Very simple.
I decided to create a new view controller and make that the new root controller. I still have the old root view controller, its just not the root anymore. So for speed, I deleted the navigation controller, selected my new root view controller, and embedded it inside of a navigation controller.
Worked perfectly. Here's what I don't understand...
My setup looks identical to what was there before, but I had to add the following to the app delegate:
LaunchController *launch = [[LaunchController alloc] initWithNibName:#"LaunchController" bundle:nil];
UINavigationController *navigation = [[UINavigationController alloc] initWithRootViewController:launch];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.window setRootViewController:navigation];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
Why did I have to add this, but the previous version didn't need it, even though I feel like the changes I made still kept the setup identical to what I had before?
Throughout the app, performSegueWithIdentifier is being called and now those always fail and say "Receiver has no segue with identifier."
If I remove the above code from the app delegate, then my root controller that's both a nib and on the Storyboard doesn't show on screen. It loads, but you can't see anything. However, now all of my segues work.
So what's going on here? I realize I probably screwed something up when creating a new navigation controller and root view controller, but I can't figure this out.
I have been spending some more time working with nibs, and I've been adding the above app delegate code, so I really don't even understand how the previous developer was making this work in the first place without that code in the app delegate.
Any help is greatly appreciated.
If you're using storyboard then you don't have to write any code in App Delegate class. Instead you mention your storyboard like Project file -> Targets -> General -> Deployment Info -> Main Interface.
Here you see Main_iPhone is my storyboard for the project. Now any View Controller inside that storyboard which is set as "Is Initial View controller" will be loaded by the app automatically for you.
Hi I'm trying navigate to view controller form the navigation view controller with connect using the objects
i want to do by programmatically but its not working its showing the black screen. Please tell me how to resolve this.
- (IBAction)reg:(id)sender {
pollpoliticalViewController *vc2 = [[pollpoliticalViewController alloc] init];
[self.navigationController pushViewController:vc2 animated:YES];
}
The above code i have used to navigate but its giving black color screen its not showing the view controller please tell me where I'm doing wrong.
Thanks.
Nothing is wrong with the above code.
As I understand what you are doing, you have a view controller class called pollpoliticalViewController. My first suggestion would be for you to look into the accepted coding style in Objective-C. You should always capitalise classes. In this instance the class should have been called 'PollPoliticalViewController`. Obviously this is not the source of the problem though.
The problem will be with the view controller itself. In the code for pollpoliticalViewController you are doing something wrong which is not displaying the view.
The view controller may actually be styled inside of a .xib file, in which case you should be initialising the view controller like this:
pollpoliticalViewController *pollVC = [[pollpoliticalViewController alloc] initWithNibName:#"pollpoliticalViewController" bundle:nil];
If the view controller is defined inside of a storyboard, you will have to give the view controller a 'Storyboard ID', for example; 'PollPoliticalVCID'. You then need to initialise it like this (assuming your storyboard is called "MainStoryboard":
pollpoliticalViewController *pollVC = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:#"PollPoliticalVCID"];
EDIT
The storyboard name is found when you open the storyboard, do not select any view controller. Open the Utilities side bar (on the right side of Xcode), select the first item, and you can find the name under Identity and Type. I have included an image.
I have a project which is already in App Store.
Now I need to add some more screens using storyboards to the project. The project was previously implemented using nib files.
I have created storyboard for the new view controller which I have added. When the view controller is called it comes up almost blank, none of the views which I have added for the controller are not showing up.
I have added below code how i'm loading the view controller from story board.
-(void)gotoEventsScreen
{
EventsListViewController* eventsScreen = [[UIStoryboard storyboardWithName:#"EventsScreen" bundle:nil] instantiateInitialViewController];
[self.navigationController pushViewController: eventsScreen animated:YES];
}
Note: I have made EventsListViewController as initialviewcontroller and it also has identifier.
I have also tried to load with identifier still it shows me the blank screen.
Actually there was some problem with my project base class view controller which consists the initWithCoder method which was not calling its super class method.
If I use the Empty template in Xcode, which just gives an app delegate and window, and I want to have a UITableView with navigation bar for drilling up and down, am I correct in assuming I should just do as below, create a UITableView subclass, instantiate it, then instantiate a navController, set the TableView as the navControllers root view and then add the navController as the root view of the Window?
It seems wrong to create a UITableViewController only to add this to another view controller subclass (UINavigationController).
Is this correct?
MyTableViewController *myTableViewController = [[MyTableViewController alloc] initWithNibName:#"MyTableViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:MyTableViewController];
[self.window setRootViewController:navController];
You are correct. That is how you use navigation controllers. They manage other view controllers. (http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/ViewControllerCatalog/Chapters/NavigationControllers.html#//apple_ref/doc/uid/TP40011313-CH2-SW27)
Yes it's correct. The navigation controller is a container whose purpose is to manage a stack of view controllers so it's very different to the table view controller. Try the master detail template and compare the differences.
You are correct. I'd also recommend you use a table view framework (such as the free Sensible TableView) to manage all your detail view controllers instead of you having to create them manually.
My app has two routes to go. Login or using the fun parts of the app. The login uses a navcontroller and the fun parts use a tab bar controller.
I would like to design my nav controller in IB in a xib and the fun parts in a separate xib file with the tab bar controller. Leaving both controllers out of the MainWindow.xib file.
Does anyone know how to do this? I would like to stay away from programmatically setting up those controllers...
The File's Owner is the LoginController a subclass of NSObject. It has 1 outlet to a UINavigationController
Drop the UINavigationController into the nib file.
Connect the navController outlet of the LoginController to the navController you just put in the nib.
Drop in a UIView from the pallet, set it to have a navigation bar at the top.
Connect the VIEW outlet of the "Root View Controller" of the UINavigationController to the view.
In the App Delegate, you now need to load the nib and file's owner but since it is an NSObject it will have to be loaded differently. First you create the file's owner (LoginController). Then, you load the nib with the file's owner. Finally, you set the windows.rootViewController to the LoginController.navController
_loginViewController = [[LoginViewController alloc] init];
[[NSBundle mainBundle] loadNibNamed:#"LoginView" owner:_loginViewController options:nil];
self.window.rootViewController = _loginViewController.navController;
[self.window makeKeyAndVisible];
Technically, the LoginViewController isn't a subclass of UIViewController but it is still the owner of the nib file. So name it however.
You should add the UITabBarController to your main XIB and show the login by creating it in code and presenting it with [self.tabBarController presentModalViewController:myLoginController animated:NO]
You might want to do this because maybe you don't want the user to login every time but save the credentials...
presenting modally also gives you the freedom over modalTransitionStyle when animating back to the tab bar controller.