Pushing multiple UIViewControllers in NavigationController - ios

I have 6 subclassed UIViewControllers connected with push segues with identifiers.
They go A>B>C>D>E>F. I am unable to find a way how to implement button in the controller A which would automatically stack all controllers up to controller F and display F controller. Stacking should be done in UINavigationController instance, not through(void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated, because if I use setViewControllers method, then I lose segue identifiers. Ty!

You should be able to do it with pushViewController:animated:, like this:
// This method belongs to view controller A class
-(void)pushToF {
// I am assuming that A is already in the navigation controller
UINavigationController *nav = self.navigationController;
UIViewController *b =[self.storyboard instantiateViewControllerWithIdentifier:#"B"];
[nav pushViewController:b animated:NO];
UIViewController *c =[self.storyboard instantiateViewControllerWithIdentifier:#"C"];
[nav pushViewController:c animated:NO];
... // And so on, until F
UIViewController *f =[self.storyboard instantiateViewControllerWithIdentifier:#"F"];
// You can push the last one with animation, so that end users would see it
[nav pushViewController:f animated:YES];
}

Related

Call another class in IOS

I'm new on IOS platform and after study a little about how does it works, i had one doubt about how to call a new class/view and overlay the current view when a button is pressed. In android i do:
Intent intent = new Intent(a.class, b.class);
startActivity(intent);
Searching on internet, i noticed that i have to use navigation bars to do it. I start an app with tab bar controller and putted a navigation controller. I used the code below:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Storyboard" bundle:nil];
UIViewController *myController = [storyboard instantiateViewControllerWithIdentifier:#"Dicas"];
[self.navigationController pushViewController: myController animated:YES];
and the return:
There is a way to overlay the current view? I always have to use navigation bars to call another class (use bottom e upper controllers will make my app ugly)?
To hide the navigation bar:
[[self navigationController] setNavigationBarHidden:YES animated:YES];
To hide tab bar:
yourViewController.hidesBottomBarWhenPushed = YES;
You can also call another viewController by using presentViewController function of a viewController class.
[self presentViewController: myController animated:YES completion:nil];
As you said u want to overlay your current view so not sure but You can show your view controller using model view like this
yourViewController *secView = [[YourViewController alloc] initWithNibName:#"YourViewController" bundle:nil];
[secView setModalPresentationStyle:UIModalPresentationPageSheet];//u can use different UIModalPresentationStyle
[secView setModalTransitionStyle:UIModalTransitionStyleCoverVertical];
[self.navigationController presentViewController:secView animated:YES completion:nil];
Above one will show your view controller over existing view controller, once presented you need to make provision to dismiss this modal view.
Simple way to present new class or ViewController like this..
ViewController *view = [self.storyboard instantiateViewControllerWithIdentifier:#"ViewController"];
[self presentViewController:view animated:YES completion:nil];

Instantiate Tab bar Controller without Segue

In all other instances I'm using a segue to transition to a tab bar controller, but I have a need now to load up a tab bar controller without a segue. To do this with a regular view I would use this:
EditProfileView *view = [[self storyboard] instantiateViewControllerWithIdentifier:#"editProfileView"];
[self.navigationController pushViewController:view animated:YES];
The EditProfileView is one of the tabs on my tab controller. How do I change this so that it loads all the tabs?
You should push the UITabBarController instead.
e.g.
UITabBarController *tc = [[self storyboard] instantiateViewControllerWithIdentifier:#"tabbarcontroller"];
[self.navigationController pushViewController:tc animated:YES];
Make sure the tabbarcontroller's storyboard ID is the same
Also, if you want to present one particular viewcontroller:
[tc setSelectedViewController:[tc.viewControllers objectAtIndex:0]];

iOS presented UINavigationController gets dismissed after it performs a popViewController

In my app i present a UINavigationController modally with a UIViewController as its rootViewController. I do it in form style. I added a second UIViewController which is also in form style and i can push to it fine. However when i perform a popViewController action after the second UIViewcontroller gets popped onto the first, the whole modally presented UIViewController gets dismissed. However i don't perform any dismissing and the dismissing function doesn't get triggered by accident either.
Any ideas why it's happening?
Sincerely,
Zoli
EDIT:
That's how i'm presenting the modal viewcontrollers with a navcontroller:
if(!welcomeScreenAlreadyPresented) {
welcomeScreenViewController = [[WAWelcomeViewController alloc]init];
}
welcomeScreenNavController = [[UINavigationController alloc]initWithRootViewController:welcomeScreenViewController];
[welcomeScreenNavController setModalTransitionStyle: UIModalTransitionStyleCrossDissolve];
[welcomeScreenNavController setModalPresentationStyle:UIModalPresentationFormSheet];
[welcomeScreenNavController setNavigationBarHidden:YES animated:NO];
[self.navigationController presentViewController:welcomeScreenNavController animated:YES completion:nil];
That's how i'm navigation in WAWelcomeViewController.m
registerViewController = [[WARegisterViewController alloc]init];
[self.navigationController pushViewController:registerViewController animated:YES];
And in WARegisterViewController.m that's how i pop back
[self.navigationController popViewControllerAnimated:YES];
What you need to do is put the viewController you want to push inside another UINavigationController.
registerViewController = [[WARegisterViewController alloc]init];
UINavigationController *modalNavigationController = [[UINavigationController alloc] initWithRootViewController:registerViewController]; // autorelease if you are not using ARC
[self presentViewController:navController animated:YES completion:^{}];
You might want to add the modalNavigationController as a property to later call popViewControllerAnimated: on it.

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.

UINavigationController with UITabViewController

I'm building an app which's delegate has a UINavigationController (navigationController). The first view is a UITabViewController (tabView) which has a UINavigationController with a UIViewController with a UITableView which shows some contacts.
What I want to do is to push a new viewcontroller with the contact's info when tapping over a contact in the tableview (over the toppest navController)
I do the following in the appDelegate:
[self.window makeKeyAndVisible];
[self.window addSubview:[navigationController view]];
TabsView *tabsView = [[TabsView alloc] initWithNibName:nil bundle:nil];
[navigationController.view addSubview:[tabsView view]];
tabsView's first tab loads ContactsView.m which has a UINavigationController with all contacts and when someone clicks on one row, it is supposed to push the new view as this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[table deselectRowAtIndexPath:indexPath animated:YES];
ContactSecondView * varContactSecondView = [[ContactSecondView alloc] initWithNibName:nil bundle:nil];
varContactSecondView.title = [[contactsArray objectAtIndex:indexPath.row] name];
[self.navigationController pushViewController:varContactSecondView animated:YES];
[varContactMapView release];
}
But nothing happens when touching in a row.
So I have different files: Delegate with UINavigationController <- UITabViewController <- UIViewController with UINavigationController with UITableView; and I want to push a ViewController into the first navigationcontroller.
How is supposed to access to delegate's navigationController? Am I doing it right?
Edit: If this gives any clue, when I do self.navigationController.title = #"Contacts"; in ContactsView.m, it's not changing the title of the topbar.
Thanks!
Two things.
It is not recommended to embed a UITabBarController in a navigation controller. It is ok to embed a UINavigationController within a UITabBarController. I know it would be a "nice to have" to embed your UITabBarController in the UINavigationController, but you may want to rethink your design so that you follow the iOS design philosophy.
Instead of adding the subview to the window in your appDelegate, try adding which ever controller you are using to the window's rootViewController property i.e,
self.window.rootViewController=navigationController;
I may be wrong, but I think you don't use the correct way to set your view controller in your navigation controller.
You do :
[navigationController.view addSubview:[tabsView view]];
I would use :
[navigationController setViewControllers:[NSArray arrayWithObject:tabsView] animated:NO];

Resources