How can you use a uinavigationcontroller at the root of a xib - ios

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.

Related

iOS - Pushing to a View Controller that is not in the Storyboard

Ok, first let's name things:
I have a table view in my root view controller wich we'll call "HomeViewController". In that table view each cell tap will push a different view controller. This collection of view controllers we'll call "DetailViewControllers".
I am perfecly aware that I can make this work by simply loading and pushing each of the DetailViewControllers programmatically inside the didSelectRowAtIndexPath method. I want to do something different instead using storyboard and a prototype cell and I'm not succeeding, so I'm looking for some advice since I'm not too well versed in storyboards and segues.
The behavior I'm trying to achieve here is:
I'll have a segue from a prototype cell in the table view in my HomeViewController. That segue pushes a "base" view controller, from which every DetailViewController inherits. These view controllers don't have an assigned view controller in the storyboard either.
In the prepareForSegue method I want to cast the 'destinationViewController' to the 'right' class. The app crashes at that point saying it "Could not cast value of type 'BaseTestViewController' to 'TestViewController'.". Which is totally understandable.
So, my question is: is there a way to make a segue work like that?
You can't create segues programatically. Segues don't exist without a storyboard. You can just push to a view controller via loading a nib file.
Here's how you do it.
Let's say you have a nib file containing the layout of the view for the main view of your view controller. We'll name it "Test" for instance.
Go to that nib file, click file's owner.
Change class to the name of your view controller. In my case, I named it ViewController.
Right click on file's owner. Link the outlet of view of your view controller to the view in the nib file.
Then in the view controller where you want to transition to that view controller, you do it like this:
UIViewController *controller = [[UIViewController alloc] initWithNibName:#"Test" bundle:[NSBundle mainBundle]];
[self presentViewController:controller animated:YES completion:nil];
It will present the view controller modally.
If you are embedding a navigation controller then you can do it like this:
[self.navigationController pushViewController:controller animated:YES];
Hope it helps.
Try like this without storyboard segue.
let objDestVC = self.storyboard.instantiateViewControllerWithIdentifier("DestVCStroyboardId") as! DestinationViewController
self.navigationController?.pushViewController(objDestVC, animated: true)

pushViewController not working read much online though

Here is what code I get online, and it does work on previous project that I develop.But in this project, self.navigationController is null when I NSLog it, and guys online talked about add some code in delegate file, but I found nothing in previous project also I am not very clear what code should I add there. Anyone can give me a hand?
UIViewController *next = [[self storyboard] instantiateViewControllerWithIdentifier:#"ViewCollection"];
[self.navigationController pushViewController:next animated:YES];
If UINavigationController is nil, it means that the view controller that you use (which you instantiate from a Storyboard) is not actually embedded within a UINavigationController.
In order to embed it into a UINavigationController, you need to drag and drop a UINavigationController into your Storyboard and then ctrl-drag from the UINavigationController to your custom view controller and set it as the rootViewcontroller of the UINavigationController.
as nburk said: you need a NavigationController with a RootViewController which is your view. and dont forget to set the NavigationController as Initial View Controller. This all is done in the IB.

iOS7 how to add a UINavigationController to a nib?

Ok so I have a view controller with a button. When that button is pressed I have another view controller that will be presented modally. I would like to embed that view controller in a navigation controller, but this can't be done programmatically, the navigation controller needs to be in the xib.
In my xib I have two objects: the navigation controller, and a view object that has all of my view controllers content. The navigations controller's view controller has its view property set to my view object.
My issue is that in my parent view controller I am trying to present the modal with this code
self.modalController = modalController.new;
self.modalController.delegate = self;
[self presentViewController:self.modalController animated:YES completion:NULL];
And then I get this crash:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Application tried to present modally an active controller <ParentController: 0xXXXXXXXX>.'
This just baffles me and I can't seem to figure out how to get passed it. I understand that this is achievable via programmatically setting up a navigation controller but I cannot use that route for this problem. Any ideas?
I have not been able to successfully instantiate any UIViewController class (or subclass) from a xib file. The only reason those object are there in Interface Builder is for use in Storyboards. You will have to figure out a way to do it in code. You can always create the UIView in a xib and then set the view of a view controller to the view loaded from a xib. There's a couple different ways to do that...
NSString *aNibName = #"customNibName";
MyViewController* myViewController = [[MyViewController alloc] initWithNibName:aNibName bundle:nil];
[navigationController pushViewController:myViewController];
Make sure to set File's Owner of the View created in Interface Builder to the UIViewController subclass.

UITableViewController done manually

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.

Load UITabBarController from XIB doesn't contain anything from the XIB

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.

Resources