Creating a UINavigationController for the first UIViewController - ios

It seems there are several approaches to creating a UINavigationController to be the very first controller. Perhaps the easiest way is to simply click the View Controller in Storyboard and embed it in a navigation controller. But I would like to know the best approach when doing this only in code.
You can subclass UINavigationController, import the first view controller, and in viewDidLoad alloc and init an instance, then add it as a childViewController. In Storyboard replace the default view controller with a navigation controller and set the class to your nav controller. Note that in previous versions of iOS it was not recommended to subclass UINavigationController.
Or you can create another UIViewController, alloc init the first view controller, then alloc init a UINavigationController with that view controller as the root, add the navigation controller as a child view controller of this view controller, and add the navigation controller's view as a subview of this view controller's view. Change the class of the view controller in Storyboard. This is an awkward setup though, because you create a view controller whose purpose is to add a nav controller but it's not a nav controller itself.
I've read about another approach which involves creating the UINavigationController in the AppDelegate. Perhaps there are even more solutions.
What is the most appropriate approach, working in the latest development environment, targeting iOS 8+?

If you're starting with a controller in the storyboard, you only need to add two lines in the app delegate to embed that controller in a navigation controller. If you want to do it in code, I think this is the simplest way,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:self.window.rootViewController];
self.window.rootViewController = nav;
return YES;
}
If you want to do it entirely in code, with no storyboard, then you need to create the window, the navigation controller, and its root view controller. You also need to click on the project icon in the files list, and in the "General" tab, delete the word "main" from the "Main Interface" pull down (that entry tells the system to start with a storyboard named "main.storyboard").
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
ViewController *vc = [ViewController new]; // You need to create this controller's view in its loadView method
vc.title = #"Root View Controller";
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
[self.window setRootViewController:nav];
[self.window makeKeyAndVisible];
return YES;
}

Related

Making your custom view controller to be the root IOS

I have a main view controller using a navigation controller and i was making my application over that. Now i want to add a welcome view controller for my app and make it show first instead of my main view controller. Is there any way to do it.
What I did was adding a view controller to my storyboard and added two classes of the same name then i made it my root view controller and unchecked the root view controller from the main view but it is not showing on the window. Please help me, that how can i make my welcome view to appear before the main view controller. Thanks
Inside Interface Builder, under the attributes section (looks like a small slider) about a quarter of the way down the list of settings, there is a section labeled "View Controller." The second item in that section is a checkbox "Is Initial View Controller," check that box and you should see the starting arrow of the story board move to the specified view controller and the app should launch to that page.
Hope this Helps.
You could do this programmatically by setting the app window's rootViewController. From the app delegate's application:didFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIScreen *mainScreen = [UIScreen mainScreen];
self.window = [[KTAppWindow alloc] initWithFrame:mainScreen.bounds];
[window makeKeyAndVisible];
window.rootViewController = [[WelcomeViewController alloc] init];
return YES;
}
Then you just need to set up your trigger to switch from the Welcome view to the main view. This could be scheduling an NSTimer, for example. Whatever the trigger is, once it occurs just change the window's rootViewController instance to your MainViewController.
I hope this helps.
It calls "Splash Screen" you just need to add a new ViewController in your Storyboard or if you don't have a Navigation Controller add.
In the Splash class, in the viewDidLoad method you need to put this:
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
HomeViewController *vc = [sb instantiateViewControllerWithIdentifier:#"Home"];
[[[[UIApplication sharedApplication] delegate] window] setRootViewController:vc];
[self performSegueWithIdentifier:#"Home" sender:self];
here you can add conditions if you needed

can we use table based navigation in single view application?

I have created single view iOS application with some basic functionality. and added the table view in simple view controller now I wanted to use table view with row navigation like(pushcontroller and popcontroller) is that possible and if it is, how we can set that.
If you need full support for push/pop operation, I would use a navigation controller.
On the other hand, you could simply present your detail view controllers when a table row is tapped:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MyViewController* detailController = <CREATE THE VIEW CONTROLLER>;
[self presentViewController:detailController animated:YES completion:NULL];
}
In this case, your detailController will need to implement a sort of navigation bar or other mechanism to let the user dismiss the controller (through dismissViewControllerAnimated:completion:) and go back to the table view. (Using a navigation controller would instead take care of this in a canonical way.)
One major drawback of the simpler solution based on presenting/dismissing is the fact that all the view controllers presented this way are dismissed at once, so you cannot have multiple levels of navigation.
EDIT:
To add a navigation controller to your app, simply do something like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
MyViewController *myViewController = [[MyViewController alloc] initWithNibName:nil bundle:nil];
...
self.navigationController = [[UINavigationController alloc] initWithRootViewController:rootViewController];
self.window.rootViewController = self.navigationController;
[self.navigationController pushViewController:myViewController animated:YES];
...
[self.window makeKeyAndVisible];
return YES;
}
At the moment, your didFinishLaunchingWithOptions method should use the addSubview method to make your main view controller (named MyViewController in my example) visible. You can replace that call by the code above to instantiate the navigation controller and push on to it your main view controller.
Alternatively, you could create a new Xcode project using the navigation-based template and move all of your source files over.

UINavigation pushing a new root controller

I am trying to push a new root controller to a navigation stack, but using a side reveal menu.
My app delegate has the following:
welcomeViewController = [[MyWelcomeViewController alloc] initWithNibName:#"MyWelcomeViewController" bundle:nil];
navController = [[UINavigationController alloc] initWithRootViewController:welcomeViewController];
navController.navigationBarHidden = YES;
// Then we setup the reveal side view controller with the root view controller as the navigation controller
self.revealSideViewController = [[PPRevealSideViewController alloc] initWithRootViewController:navController];
[self.revealSideViewController setDirectionsToShowBounce:PPRevealSideDirectionNone];
[self.revealSideViewController setPanInteractionsWhenClosed:PPRevealSideInteractionContentView | PPRevealSideInteractionNavigationBar];
// Then we make the window root view controller the reveal side view controller
self.window.rootViewController = self.revealSideViewController;
Once the welcome view controller is displayed, the user logs in. Once logged in the following process runs again from the App Delegate.
self.navController.navigationBarHidden = NO;
[self.navController setTitle:#"Home"];
[self.navController pushViewController:homeViewController animated:NO];
I then have a side view controller setup which is a table view with custom cells setup.
When a row is selected I need to push a new root controller onto the navigation controller. I try this by using the following in the table view for the cell selected.
MyAccountViewController *accountViewController = [[MyAccountViewController alloc] init];
[self.navigationController setViewControllers:[NSArray arrayWithObject:accountViewController] animated:NO];
Unfortunately this does not do anything. If I add the code to the App Delegate and then call the method from the table view controller then it works, however not from the .m file for the table view itself. Adding a log I can see the above is run, just does not do anything.
I am unsure if I need to do anything different on the above. For example, completely pop the views currently shown, then create the navigation controller and PPRevealSideViewController all over again. If I am supposed to, I am unsure how to pop all the current views to then push the new to the window, not from the AppDelegate.
The reason I do not want this in the App Delegate is because it is the incorrect way to approach this, and I would then need a separate method for each new root controller I would like to push from the menu, so the App Delegate would become very large.
Check UINavigationController.h:
#interface UIViewController (UINavigationControllerItem)
#property(nonatomic,readonly,retain) UINavigationController *navigationController; // If this view controller has been pushed onto a navigation controller, return it.
It means when you do myViewController.navigationController you will either get nil if myViewController is not pushed to any navController or the navController reference myViewController is pushed into.
As I understand your tableViewController is not pushed into the navController stack, that means you can't get the navController with tableViewController.navigationController. Instead you'll need to use anyViewControllerInTheStack.navigationController or if the navController is the rootViewController of your keyWindow, by
((UINavigationController*)[[UIApplication sharedApplication] keyWindow].rootViewController)
Add something like this to your AppDelegate.h:
#define XAppDelegate ((AppDelegate *)[[UIApplication sharedApplication] delegate])
Now you can access any iVar of AppDelegate from any .m file in your project.
MyAccountViewController *accountViewController = [[MyAccountViewController alloc] init];
[XAppDelegate.navController pushViewController:accountViewController animated:NO];
Make sure you add the correct imports.
One more thing: It's good to pop the login window from your navcontroller once you are done Logging in.
Hope this helps.

iOS: Adding navigation bar from XIB

I have been seeing this issue and resolving it by manually creating UINavigationController in the code. Could someone please tell me when I add Navigation Bar from XIB's Attribute Inspector -> Set Top bar to Black Navigation bar, it gets displayed in the XIB but when I run the program, it doesn't appear! I noticed that self.NavigationController was coming nil so I added UINavigationController in my XIB and assign NIB but still it's nil! What's wrong with this? Do I need any additional settings?
[EDIT1]
I tried adding it like below and it works but I want parent class to forward rotation and appearance events to child controller automatically. If I do following it won't send them because I am adding nvc as child and not marketsListViewController. So I thought I have to subclass UINavigationController. See EDIT2.
self.marketsListViewController = [[MarketsListViewController alloc] initWithNibName:#"MarketsListViewController" bundle:nil];
UINavigationController *nvc = [[UINavigationController alloc] initWithRootViewController:self.marketsListViewController];
nvc.navigationBar.barStyle = UIBarStyleBlack;
[self.marketsListView addSubview:nvc.view];
[self addChildViewController:nvc];
[nvc didMoveToParentViewController:self];
[EDIT2]
I have subclassed marketsListViewController to UINavigationController and thought following will work but it doesn't. It just displays navigation bar, UITableView doesn't get displayed!
self.marketsListViewController = [[MarketsListViewController alloc] initWithNibName:#"MarketsListViewController" bundle:nil];
self.marketsListViewController.navigationBar.barStyle = UIBarStyleBlack;
[self.marketsListView addSubview:self.marketsListViewController.view];
[self addChildViewController:self.marketsListViewController];
[self.marketsListViewController didMoveToParentViewController:self];
[EDIT3]
I was wrong in Edit1 that children controller won't get rotation events when I add child as navigation controller's root controller. Parent still sends all the events automatically and that's what I want! :)
Could someone please tell me when I add Navigation Bar from XIB's
Attribute Inspector -> Set Top bar to Black Navigation bar, it gets
displayed in the XIB but when I run the program, it doesn't appear!
What you see in you .xib file is just there to help you get your layout right and get a good idea of what it'll look like. When you have an app that uses a navigation bar, the bar is almost always managed by a navigation view controller (UINavigationController). The view controllers that the navigation controller hosts don't worry about the nav bar -- their view hierarchies go in the space beneath the bar.
So, the right way to get a navigation bar in your app is almost certainly to use a navigation controller. If you only have one view controller, make that that the navigation controller's root view controller (note: the root view controller of the window will be the navigation view controller). You can change the appearance of the bar from your view controller by setting the navigation bar's style:
self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
Update: In the code you posted, you're just creating a new navigation controller, but not doing anything with it. I alluded above the the fact that (in most cases) the navigation controller should be the window's root view controller. It's fine to create your navigation controller in code, but you'll usually do it in the app delegate, and once you create it you'll set it as the window's root view controller. Here's an example borrowed from a project made fresh from Xcode's master/detail template (sans storyboards):
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:#"MMMasterViewController" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
Note that after creating the window and the navigation controller, the code sets the nav controller as the window's root view controller.

Initializing root view controller with myViewController / Using split view(sliding navigation) controller

I'm working on adopting slide (split) view controller to my project.
JT, DD, ZUUI, JW, ECS.....
All these sources suggesting initialize my root view controller in appDelegate.
Something like this....
MyMainViewController *controller = [MyMainController alloc] init];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:Controller];
.........
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
Problem is I can't make my view visible, my app show blank page only with a empty navigation bar.
I customized my main view using AQGrid, is this causing a problem?
My view looks different to storyboard look. (because I customized it.)
So when I do initialize I'm using "self.storyboard initialize......method".
But in appdelegate, I can't use that method.
Simply, I can't make this view hierarchy because when I initialize my view it is not visible.
ZUUIRevealController is parent of:
UINavigationController is parent of:
FrontViewController
If you are using a storyboard, don't do any of that. Instead, choose your starting view controller from the storyboard and check the "Is Initial View Controller" in the Attributes inspector.

Resources