Double UINavigationBar in UITabBarController - ios

We have a UINavigationViewController as root viewController in AppDelegate:
Restore *callRestore=[[Restore alloc]initWithNibName:#"Restore" bundle:nil];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:callRestore];
self.window.rootViewController = self.navigationController;
We are pushing a new viewController (TabViewController) from above Restore:
callTabView=[[TabViewController alloc] initWithNibName:#"TabViewController" bundle:nil];
[self.navigationController pushViewController:callTabView animated:YES];
In this TabViewController we are adding UITabBarController programatically as subview and in this UITabBarController we have 5 UINavigationBarController as view controllers:
NSArray* controllers = [NSArray arrayWithObjects:navControllerDashboard, navControllerAccounts, navControllerTransation,navControllerCallDisplayReports,navControllerMore, nil];
self.tabBarController.viewControllers = controllers;
self.tabBarController.delegate = self;
self.tabBarController.view.frame = self.view.frame;
[self.view addSubview:self.tabBarController.view];
When we are rotating any view from these 5 UINavigationViewController we are getting 2 UINavigationBar on top in both landscape and portrait mode.
Check below image.
and didRotateFromInterfaceOrientation is not calling from these 5 UINavigationViewController view.
Any help?

When you add a view controller to another one as a subview manually you have to do the following:
UIViewController *parent = ...;
UIViewController *child = ...;
[child willMoveToParentViewController: parent];
[parent addChildViewController: child];
[parent.view addSubview: child.view];
[child didMoveToParentViewController:parent];
This will propagate all the events to the child view controller and possibly remove unexpected behaviour.

Related

present a new ViewController but maintain the view stack

I'm trying to update an old IOS (objective-c) app to handle shortcutitems. When the user starts the app from a shortcut I would like to go the viewcontroller they've chosen, but would like them to be able to move back through the view hierarchy, to the original launch screen.
the current code in appdelegate didFinishLaunchingWithOptions looks like this:
UINavigationController *controller = (UINavigationController*)[storyboard instantiateInitialViewController];
self.window.rootViewController = controller;
return YES
And trying this:
UINavigationController *controller = (UINavigationController*)[storyboard instantiateInitialViewController];
self.window.rootViewController = controller;
...
if (fromShortCut) {
InfoViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"info"];
// init vc
vc.info = .....
[controller.navigationController pushViewController:vc animated:NO];
// or [controller pushViewController:vc animated:NO];
}
return YES
Shows the correct View, but there's no Back/Back-arrow or swipe gesture to allow the user to move back to the main screen.
Is this possible?
Many Thanks.
Here you go for your solution
if (fromShortCut) {
InfoViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"info"];
UIViewController *rootController = [UIApplication sharedApplication].keyWindow.rootViewController;
// init vc
vc.info = .....
[rootController.navigationController.navigationBar setHidden:NO];
[rootController.navigationController pushViewController:vc animated:NO];
// or [controller pushViewController:vc animated:NO];
}
else{
UINavigationController *controller = (UINavigationController*)[storyboard instantiateInitialViewController];
self.window.rootViewController = controller;
}
Yes. This is possible.
UINavigationController has a setViewControllers:animated: method that lets you do exactly that.
Pay attention to the documentation here:
viewControllers
The view controllers to place in the stack. The
front-to-back order of the controllers in this array represents the
new bottom-to-top order of the controllers in the navigation stack.
Thus, the last item added to the array becomes the top item of the
navigation stack.
You should create an array of UIViewController objects and the order should like this.. [firstVC, secondVC, ..., topMostVC]
EDIT:
The code should look something like this
UINavigationController *controller = (UINavigationController*)[storyboard instantiateInitialViewController];
self.window.rootViewController = controller;
if (fromShortCut) {
NSMutableArray *viewControllers = [[NSMutableArray alloc] init];
//create other viewonctollerObjeccts
FirstViewController *firstVC = storyboard instantiateViewControllerWithIdentifier:#"first"];
SecondViewController *secondVC = storyboard instantiateViewControllerWithIdentifier:#"second"];
ThirdViewController *thirdVC = storyboard instantiateViewControllerWithIdentifier:#"third"];
InfoViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"info"];
// init vc
vc.info = .....
[viewControllers insertObject:vc atIndex:0];
//finally set the array to nav stack
[controller setViewControllers:viewControllers animated:NO];
}
What this does is, it sets InfoViewController at the top of the navigation stack, and backs out to ThirdViewController which backs out to SecondViewController and so on.

display a SplitViewController from UIViewController in Objective-C

I am developing a ViewController (login app) with a single button, when I press this button I want to appear my UISplitView like this:
- (IBAction)loadSplitViewController:(id)sender {
[self showSplitViewController];
}
and the code developed for the creation of my splitViewController is this:
-(void)showSplitViewController{
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPad" bundle: nil];
LeftViewController *leftViewController = [mainStoryboard instantiateViewControllerWithIdentifier:#"LeftViewController"];
RightViewController *rightViewController = [mainStoryboard instantiateViewControllerWithIdentifier:#"RightViewController"];
UINavigationController *leftNavController = [[UINavigationController alloc] initWithRootViewController:leftViewController];
UINavigationController *rightNavController = [[UINavigationController alloc] initWithRootViewController:rightViewController];
UISplitViewController *splitViewController = [[UISplitViewController alloc] init];
splitViewController.viewControllers = [NSArray arrayWithObjects:leftNavController, rightNavController, nil];
leftViewController.delegate = rightViewController;
splitViewController.delegate = rightViewController;
[self presentViewController:splitViewController animated:YES completion:^{}];
}
the thing is... if I use for display my splitViewController this line:
[self presentViewController:splitViewController animated:YES completion:^{}];
throws me an error
I also tried with
[self.view addSubview:splitViewController.view];
but this way my splitViewController never rotates, and delegates doesn't work as well... and I don't want my splitViewController to be a subview of my viewController, I want it to appear more like an independient modalView
any help I'll appreciate
thanks in advance
Split view controllers really should be the root view controller of the window (in fact Apple says it has to be, though there seem to be some examples where this isn't true). Instead of presenting it, you could just switch the window's root view controller to be the split view controller.
self.view.window.rootViewController = splitViewController;

Run UIViewController inside UINavigationController as a second view of UISplitViewController

I have a problem trying to access a navigation controller of the view controller from it, always returns as nill to me, though it is shown within the navigation controller.
Here is what I have (I have a split view controller, that is presented as tab controller for master and viewcontroller (inside navigation controller) as detail):
FirstDetailViewController *fdvc = [[FirstDetailViewController alloc] initWithNibName:#"FirstDetailViewController" bundle:nil];
UINavigationController *fdvcNav = [[UINavigationController alloc] initWithRootViewController:fdvc];
NSArray *ipadVCs = [[NSArray alloc] initWithObjects:tabController, fdvcNav, nil];
UISplitViewController *splitvc = [[UISplitViewController alloc] initWithNibName:nil bundle:nil];
[splitvc setViewControllers:ipadVCs];
[[splitvc view] setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"splitViewControllerBG"]]];
[splitvc setDelegate:fdvc];
[[self window] setRootViewController:splitvc];
[[self window] makeKeyAndVisible];
But when I'm trying to access a navigation controller from the fdvc view controller in ViewDidLoad with [self navigationController] it gives me (Null) always.
Thanks!
I fixed it. Turned out, that I had to move my code from ViewDidLoad method to ViewDidAppear and it worked fine.
viewDidLoad is getting called before the navigationController property has been updated, that was my mistake.

Pushing a navigation controller is not supported

In my MainStoryBoard I want to push a viewController to the detailView but I get this error:
NSInvalidArgumentException', reason: 'Pushing a navigation controller is not supported'
I set the identifier 'JSA' ID for the viewController on the storyboard.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
SWSJSAViewController *viewController = [[UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:#"JSA"];
[self.navigationController pushViewController:viewController animated:YES];
}
}
Like rmaddy said in the comments you are trying to push a navigation controller.
Navigation controllers should be presented (via presentViewController or they can be added as a childViewController) and ViewControllers should be pushed.
When you talk about pushing Navigation Controller, it is most likely that you want to present it.
Presenting UINavigationController
This is the most common way and this is what you want to do in most cases. UINavigationController cannot be pushed, it can only be presented with a new root View Controller.
MyViewController* vc = [[MyViewController alloc]
initWithNibName:#"MyController" bundle:nil];
UINavigationController *myNav = [[UINavigationController alloc] initWithRootViewController: vc];
[self presentViewController:myNav animated:YES completion:nil];
What you do here, is firstly create a UINavigationController and then set necessary UIViewController as its root controller.
Pushing UINavigationController
If you have a hierarchy of ViewControllers and you need to push view controller that contains navigation controller within, steps are:
1) Push ViewController, containing UINavigationController.
To push UINavigationController, first create a subclass of UIViewController, which will be a wrapper-/container- class for your UINavigationController and its content.
ContainerViewController* vc = [[ContainerViewController alloc] init];
2) Adding UINavigationController as a child view controller
In viewDidLoad of your container (that you have just instantiated) simply add something like this:
Objective-C
UINavigationController* myNav = [[UINavigationController alloc] initWithRootViewController: rootViewController];
[myNav willMoveToParentViewController:self];
myNav.view.frame = self.view.frame; //Set a frame or constraints
[self.view addSubview:myNav.view];
[self addChildViewController: myNav];
[myNav didMoveToParentViewController:self];
Swift 4.2+
let childNavigation = UINavigationController(rootViewController: viewController)
childNavigation.willMove(toParent: self)
addChild(childNavigation)
childNavigation.view.frame = view.frame
view.addSubview(childNavigation.view)
childNavigation.didMove(toParent: self)
What you do here is basically instantiate your navigation controller and add it as a child controller to your wrapper. That's it. You have successfully pushed your UINavigationController.

my UINavigatioBar is not on the top of view - programmatically

I am creating a UINavigationBar using the following,
UINavigationController *navigationController = [[UINavigationController alloc] init];
[view addSubview: navigationController.view];
How come it shows up like this?
(source: gyazo.com)
I want it to be on the top of the view but there is space there, why?
Thanks.
You are not creating things correctly. You should create your view controller, then create a navigation controller, passing the view controller as the nav controller's root controller. Then you make the nav controller the app's root controller.
UIViewController *vc = ... // create your view controller
UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:vc];
window.rootViewController = nc;
The code you posted does not create a nav bar, it creates an entire navigation controller.
Put this code to ViewWillAppear
- (void)viewWillAppear {
UINavigationController *navigationController = [[UINavigationController alloc] init];
[view addSubview: navigationController.view];
}
Also you should resize nav controller to self controller bouns

Resources