NavigationController Header Disappears when loading from AppDelegate - ios

In my AppDelegates 'didFinishLaunchingWithOptions' function, I have this code in there:
if(loggedIn != nil)
{
MainViewController *mvc = [self.window.rootViewController.storyboard instantiateViewControllerWithIdentifier:#"MainView"];
[self.window setRootViewController:mvc];
}
Second Attempt which didn't work:
if(loggedIn != nil)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
MainViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"MainView"];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
[self.window setRootViewController:nav];
}
The problem is that when the MainViewController loads, the NavigationHeader is missing. I've tried various methods online and instantiations that basically do the same thing to no avail. I have also tried created a whole new navigationController and adding my view to it, however, that fails as well.

Your setting MainViewController as your root, if this is not a navigation controller, there will be no header when it opens.
Instead create a UINavigationController, set MainViewController as its root and then set the navigation controller as the window root.
e.g.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"storyboardName" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"home"];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc];
[self.window setRootViewController:nav];
or if you have the navigation controller inside the storyboard then instantiate that. Most likely the initial view controller.
e.g.
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"storyboardName" bundle:nil];
[self.window setRootViewController::[storyboard instantiateInitialViewController]];
not sure if it will be the initial viewController or not, that requires more info of your setup to know.

Related

alloc init does not load component in it

i am using UINavigationController but when i push a view controller just simply by making object of the class the class load but not the components in it.
this is my AppDelegate.m
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewController *vc = [sb instantiateInitialViewController];
UINavigationController *nav = [[UINavigationController alloc] init];
self.window.rootViewController = nav;
nav.viewControllers = #[vc];
and my first UIViewController if action button code is
NextView *next = [[NextView alloc] init];
[self.navigationController pushViewController:next animated:YES ];
it gets to next UIViewController but no internal components are loaded such as - button,textfield,etc.
and if i try this code it give me runtime error
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
NextView *next = [sb instantiateViewControllerWithIdentifier:#"two"];
[self.navigationController pushViewController:next animated:YES ];
make sure that NextView inherit UIViewController and you have given identifier as two to that view controller and you have set class NextView from identity inspector to that viewcontroller.
Hope this will help :)
You could not get outlets (buttons etc.) to be loaded with alloc init in the subclass of UIViewController. You should init it with the xib file, using -initWithNibName:bundle: method. Or you can instantiate it with storyboard.
// You can get current storyboard from the View Controller
UIStoryboard *sb = vc.storyboard;
NextView *next = [sb instantiateViewControllerWithIdentifier:#"two"];
[self.navigationController pushViewController:next animated:YES];

iOS/xcode/objective-c: How to instantiate view controller after signup

After a successful sign up, I want users to go through a process where they provide photo etc. Similar code to that below worked to load the login page but code below is not working to load a separate view controller in storyboard "newuser".
Would appreciate any suggestions on how to fix.
- (void)presentNewUserInterface
{
UIViewController* rootController = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"newuser"];
UINavigationController* navigation = [[UINavigationController alloc] initWithRootViewController:rootController];
self.window.rootViewController = navigation;
}
Instead of:
- (void)presentNewUserInterface
{
UIViewController* rootController = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"newuser"];
UINavigationController* navigation = [[UINavigationController alloc] initWithRootViewController:rootController];
self.window.rootViewController = navigation;
}
Try:
- (void)presentNewUserInterface
{
UIViewController* rootController = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"newuser"];
UINavigationController* navigation = [[UINavigationController alloc] initWithRootViewController:rootController];
[self presentViewController:navigation animated:YES completion:nil];
}
You aren't presenting your new navigation controller in your example. Is there a particular reason why you would be trying to replace your rootViewController? That shouldn't be needed. My example should be sufficient for displaying your next flow in the user sign up process.
Two variants:
Replace window.rootViewController with your next view
controller. Do it on AppDelegate class.
Present new view controller
from current root view controller. Do it in your sign up view
controller.
The lack of the first method is no transaction animation. So second method is preferable.

Setting a RootViewController with UINavigationController Programmatically

I have a program with a Navigation Controller and a default RootViewController. If I do nothing programmatically, the app launches and the RootViewController works as I expect, such as what the storyboard below denotes:
The issue that I have is by incorporating the Optional Start ViewController. What I want is this: In my AppDelegate (didFinishLaunchingWithOptions), I want to have code like this:
UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"OptionalStartViewController"];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
To first show the Optional Start ViewController. Then, after the user has finished with the Optional viewcontroller, they can then display the RootViewController.
So in the Optional Start ViewController, I've added code like this to show the Root View Controller:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"RootViewController"];
[self appDelegate].window.rootViewController = viewController;
[[self appDelegate].window makeKeyAndVisible];
This all works except the RootViewController, when shown, does not have the navigation controls as expected (i.e. the view is shown without navigation controls).
I've also tried the code below (using UINavigationController instead of ViewController) with the same results...
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle: nil];
UINavigationController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"HomeViewController"];
[self appDelegate].window.rootViewController = viewController;
[[self appDelegate].window makeKeyAndVisible];
One other twist... there could be several optional start view controllers.
Any ideas?
Delete the UINavigationController
select the controller ("optional start view controller" in our case)
click Editor >> Embed In >> Navigation Controller
Now select the Navigation Controller and Right Side Utility area, Select the option Is Initial View Controller
If you want to change the root view controller dynamically then its better to do it programmatically, in didFinishLaunchingWithOptions, Get the window instance , initialize navigation controller with the root view controller and then set windows root view controller to navigation controller.
Here is the code.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
OptionalFirstViewController *optionalFirstViewController = [[OptionalFirstViewController alloc] initWithNibName:#"OptionalFirstViewController" bundle:nil];
UINavigationController *homeNavigationController = [[UINavigationController alloc] initWithRootViewController:optionalFirstViewController];
[optionalFirstViewController release];
self.window.rootViewController = homeNavigationController;
[homeNavigationController release];
[self.window makeKeyAndVisible];
return YES;
}
and make sure that you uncheck Is Initial View Controller for all view controllers in story board
Hope this helps
Without using storyboard we can set programmatically in AppDelegate Class, just write down these lines of code in AppDelegate.
AppDelegate.h
#property (strong, nonatomic) UIStoryboard *storyboard;
#property (strong, nonatomic) UINavigationController *navigationController;
AppDelegate.m
if(self.window == nil)
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
if(self.navigationController == nil)
self.navigationController = [[UINavigationController alloc]init];
if(self.storyboard == nil)
self.storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
self.navigationController.navigationBarHidden = YES;
// Here we can check user is login or not also,
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewController *ivc = [storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
[self.navigationController pushViewController:ivc animated:YES];
self.window.rootViewController = ivc;
[self.window setRootViewController:self.navigationController];
[self.window makeKeyAndVisible];
In Swift Version
var window: UIWindow?
var storyBoard :UIStoryboard?
var navigationController : UINavigationController?
var mainController :MainViewController = MainViewController()
if window == nil {
window = UIWindow(frame: UIScreen.main.bounds)
}
if navigationController == nil {
navigationController = UINavigationController()
}
if storyBoard == nil {
storyBoard = UIStoryboard(name: "Main", bundle:nil)
}
navigationController?.setNavigationBarHidden(true, animated: true)
// storyboard with identifer
mainController = storyBoard?.instantiateViewController(withIdentifier: "MainViewController") as! MainViewController
navigationController?.pushViewController(mainController , animated: true)
window?.rootViewController = navigationController
window?.makeKeyAndVisible()
You can't set a new root view controller to UINavigationController after it is initialised. You should modify viewControllers array of UINavigationController according to your needs.
If you want the optional VC to be root VC, create #[optionalVC] and set it as viewControllers array of UINavigationController.

top bar not visible after programmatically pushing UINavigationController

In the AppDelegate i check if there is a user existing, if there is i "skip" two ViewControllers by pushing a NavigationController using this code:
if(currentUser){
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"Test"];
self.window.rootViewController = viewController;
viewController.navigationController.navigationBarHidden = NO; // Tried this nothing happened.
[self.window makeKeyAndVisible];
}
else{
[PFUser enableAutomaticUser];
[[PFUser currentUser] incrementKey:#"RunCount"];
[[PFUser currentUser] saveInBackground];
[[PFUser currentUser] fetch];
self.window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"firstView"];
self.window.rootViewController = viewController;
[self.window makeKeyAndVisible];
}
So the true statement skips two ViewControllers and push the UINavigationController. But when it shows it this way there is no top bar.
However if there was no user then it would proceed to the UINavigationController in a "normal" way by segues then the bar is visible.
How can i fix this?
Thank you!
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main"
bundle:nil];
UIViewController *viewController = [storyboard
instantiateViewControllerWithIdentifier:#"Test"];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:viewController];
self.window.rootViewController = nav;
"So the true statement skips two ViewControllers and push the UINavigationController." No, it doesn't. First of all you're not pushing anything, you're setting the window's root view controller. Secondly, you haven't created any navigation controller, you've only created viewController.
If viewController has a navigation controller in the storyboard, then you should instantiate the navigation controller (which will, in turn, instantiate viewController), and make it the window's root view controller.
I think you should set a UINavigationController to rootviewController , there will be a navigation bar. So you can also set the firstView as rootViewController, but set the viewcontrollers attribute to put the Test viewcontroller that clears before viewcontrollers.

ios adding navigation before splitview controller

I want to add a navigation view controller prior to the user getting to the splitview controller. I have tried a few ways of changing the root controller when I want to go from navigation controller to splitview controller but I don't seem to be setting the delegate the right way when I do this.
Code WITHOUT nav view (works perfectly):
AppDelegate
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
splitViewController.delegate = (id)navigationController.topViewController;
UINavigationController *masterNavigationController = splitViewController.viewControllers[0];
MasterViewController *controller = (MasterViewController *)masterNavigationController.topViewController;
controller.managedObjectContext = self.managedObjectContext;
Code with nav view prior to SplitView
AppDelegate
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UIViewController* rootController = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateViewControllerWithIdentifier:#"dummy"];
self.window.rootViewController = rootController;
[self.window makeKeyAndVisible];
DummyViewController
AppDelegate *appDelegateTemp = [[UIApplication sharedApplication]delegate];
appDelegateTemp.window.rootViewController = [[UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]] instantiateInitialViewController];
This takes me from the DummyViewController that I launched into, to the splitview controller which is the initial view controller in Storyboard. Which is fine however, when I do it this way none of the delegates get called. This is probably because when changing root controllers, it is not setting the delegates properly. How can I get this to work the right way?
It seems the only really non-hacking way to do it is to present a modal view over the split view in the detail view controller
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
DummyViewController *dummy = (DummyViewController *)[storyboard instantiateViewControllerWithIdentifier:#"dummy"];
[self presentViewController:dummy animated:NO completion:nil];
By setting animation to NO, the user does not see the split view loaded behind it.

Resources