I have three UIViewControllers and one separate viewcontroller with UISegmentControl where i have to push 3 viewcontrollers using navigationControllers. I want all these views to appear below UISegmentControl when any segmentcontrol is selected. I tried push and pop logic, but couldn't get the result right. Below is the code for one controller-
-(IBAction)valueChanged:(id)sender{
segmentControl=(UISegmentedControl*)sender;
if (segmentControl.selectedSegmentIndex==1) {
firstView = [self.storyboard instantiateViewControllerWithIdentifier:#"FirstTopViewController"];
[self.navigationController pushViewController:firstView animated:YES];
[self.navigationController popViewControllerAnimated:NO];
self.navigationController.navigationItem.titleView=segmentControl;
NSLog(#"1");
}
}
Can anyone tell me what i'm doing wrong here?
Related
I have a Tabbarcontroller filled with 5 Viewcontrollers and Navigationcontrollers as I did here:
[self addChildViewController:VC1];
[self addChildViewController:NavigationController;
[self addChildViewController:VC2];
[self addChildViewController:VC3];
[self addChildViewController:VC4];
Now the thing is, that pressing a button on my Tabbar gets me to every ViewController easily, where I can present Xib-Files etc.
But now I want to have a Navigationcontroller, which is shown when pressing a button on my Tabbar. This Navigationcontroller itself has several Viewcontrollers.
I tried this to present my first Viewcontroller inside my Navigationcontroller (this code is from the Navigationcontroller.m):
- (void)viewDidLoad {
[super viewDidLoad];
[self addChildViewController:VC5];
[self presentViewController:VC5];
}
This expectedly did not work and gave me: Application tried to present modally an active controller.
Is there a good way to achieve such a specific goal? I'm struggling with this problem. Thanks in advance!
edit: This is how I set it up in my storyboard. In my programmatic approach the first view controller is not shown.
Instead of adding the VC5 view controller to the NavigationController as a child (unless it's meant to be a child?) add it as the root view controller when you add the NavigationController to the tab bar.
For example in your tab bar code:
[self addChildViewController:VC1];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:VC5];
[self addChildViewController:navigationController];
[self addChildViewController:VC2];
[self addChildViewController:VC3];
[self addChildViewController:VC4];
Apple docs on UINavigationController are here: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/#//apple_ref/occ/instm/UINavigationController/initWithRootViewController:
I have an UITabBarController that has 3 buttons. The second button points to ViewController1 which is connected to another view called ViewController2. After I tap a button in ViewController2 I programmatically present ViewController1 again, that works perfect except one thing. After I "arrived" to ViewController1 the tab bar disappears.
I'm using this method to navigate back to ViewController1. (exactly I navigate to its navigation controller, but already tried with the view)
- (void)presentViewControllerAnimated:(BOOL)animated {
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"storyboard" bundle:nil];
UINavigationController *firstViewNavigationController = [storyboard instantiateViewControllerWithIdentifier:#"destination"];
[self presentViewController:firstViewNavigationController animated:animated completion:nil];
}
I call here the first method
- (void)didTapButton:(id)sender {
UIButton *button = (UIButton *)sender;
CGPoint pointInSuperview = [button.superview convertPoint:button.center toView:self.tableView];
[self presentViewControllerAnimated:YES];
}
This method hides the tab bar in the ViewController2, I already tried without it, therefore there is no problem with it.
-(BOOL)hidesBottomBarWhenPushed
{
return YES;
}
I can't figure out why this thing happens, I think it's a fair solution, that worked well for a several times when I needed to present views. I've read it can happen with segues, but I'm doing it with code without segues.
Actually your code works right. There should not be tab bar when you present FirstViewController from SecondViewController. Because when you call instantiateViewControllerWithIdentifier its basically creates a new instance of that view controller, and of course, there is no tab bar.
The right way to go back to your first view controller is to pop SecondViewController (or dismiss it, if it presented modally). So your final code should be like this
- (void)didTapButton:(id)sender {
// If this view controller (i.e. SecondViewController) was pushed, like in your case, then
[self.navigationController popViewControllerAnimated:YES];
// If this view controller was presented modally, then
// [self dismissViewControllerAnimated:YES completion:nil];
}
And of course, your view controller hierarchy in storyboard must be like this:
-- UINavigationController -> FirstViewController -> SecondViewController
|
->UITabBarController____|
-...
-...
I've tried the same and got the same result.
My solution was simple, on the push do this :
UINavigationController *firstViewNavigationController = [storyboard instantiateViewControllerWithIdentifier:#"destination"];
firstViewNavigationController.hidesBottomBarWhenPushed = true; // Insert this and set it to what you want to do
[self presentViewController:firstViewNavigationController animated:animated completion:nil];
and then remove your
-(BOOL)hidesBottomBarWhenPushed
{
return YES;
}
In my program have 6 view controllers.(in storyboard)
Lets define 1,2,3,4,5,6.
1 is my main view.
I want to navigate like this(image bellow).Is it possible to do?
give me a idea to do this navigation.
Yes, u can implement this. This is a simple navigation in iOS using NavigationController.
you have six viewControllers 1, 2, 3, 4, 5, 6.
to do this:
First create a NavigationController and initialize it with ViewController 1 (ie a root View Controller).
Now your navigationController behaves like a stack which contains all ur pushed view controller. NavigationController is only push and pop ur view controllers.
So, every time when u want to navigation first check ur viewController is inside navigationController stack or not. If it is already in stack then pop to that controller, if not then push the same view controller.
for this use following:
In case ViewController3
-(void)popToSelectedViewController
{
NSArray *vc=[self.navigationController viewControllers];
ViewController3 *vc3=nil;
for (int i=0; i<[vc count]; i++)
{
UIViewController *tempVC=[vc objectAtIndex:i];
if([tempVC isKindOfClass:[ViewController3 class]])
{
vc=[vc objectAtIndex:i];
break;
}
}
if(vc3)
{
//If exists inside stack the pop
[self.navigationController popToViewController:vc3 animated:YES];
}
else
{
//If not exists inside stack push ViewController3
ViewController3 *vc3New= [[ViewController3 alloc]initWithNibName:#"ViewController3" bundle:nil];
[self.navigationController pushViewController:vc3New animated:YES];
[vc3New release];
}
}
For initializing ur ViewController1 with navigationController:
if using storyboard
Embed ur initialViewController(ie viewController3) with UINavigationController.
for this:
Step1: open storyboard, and select ur initialViewController(ie viewController3).
Step2: Go to Editor in menu -> Choose Embed In -> Select UINavigationController.
this creates a navigationcontroller and initializes with viewController3 as rootViewController.
if not using storyboard
make property of vc3 (ViewController3) and applicationNavigationController (UINavigationController) in .h
and in .m:
got method "application... didFinishedLaunching...." in appDelegate
and write:
self.vc3=[[ViewController3 alloc]initWithNibName:#"ViewController3" bundle:nil];
self.applicationNavigationController=[[UINavigationController alloc] initWithRootViewController:self.vc3];
self.window.rootViewController=self.applicationNavigationController;
[self.window makeKeyAndVisible];
First You create a navigation controller object
UINavigationController *navCtrl = [[UINavigationController alloc]initWithRootViewController:rootViewController];
self.window.rootViewController = navCtrl;
If you want to go to 1->2,1->3,1->6,etc, create an object for the next viewcontroller and push it to navigation stack
[self.navigationController pushViewController:second animated:YES];
You dont need to do any additional work to go back to the previous view controller. The default back button lets you go back.
If you need to return to the root view controller, then use this:
[self.navigationController popToRootViewControllerAnimated:YES];
if you want to return to any particular view controller, then use this
[self.navigationController popToViewController:viewController animated:YES];
Use UINavigationController.It is nor circular.It can be assumed as stacked approch.That is what navigation controller do
A must read for you
I need to jump between view controllers. For example:
View1: First screen (Just logo)
View2: Download Screen
View3: First app screen (Some Buttons)
View4-View(N): some app screens
When user enters app the app goes to View1->View2 (downloads stuff)->View 3->View4->View5
Then user wish to go to First app screen (View3) he does:
NSArray *array = [self.navigationController viewControllers];
[self.navigationController popToViewController:[array objectAtIndex:2] animated:NO];
The first time user enters the app it goes: View1->View3 (The download screen no longer needed), and I have different push segue to go to View3 so lets assume the user goes to: View1->View 3->View4->View5, now he wishes to go back to View3, so the function:
NSArray *array = [self.navigationController viewControllers];
[self.navigationController popToViewController:[array objectAtIndex:2] animated:NO];
Will return him to View4, and this is WRONG. How can I solve it?
Well if you are using storyboards , what you can do is set your uiviewcontrollers' storyboard id and use it for popping and pushing your views.
Lets say your Storyboards name is MainStoryboard.storyboard
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"MainStoryboard"
bundle:nil];
SettingsListViewController *settingsVC = [sb instantiateViewControllerWithIdentifier:#"SettingsListViewController"]; // #"SettingsListViewController" is the string you have set in above picture
[self.navigationController popToViewController:settingsVC animated:YES];
Above solution should work for you , but If I were you I would change the structure of my app , you say :
View1: First screen (Just logo)
View2: Download Screen
Since View1 is just logo and View 2 is also a view that you skip, you can remove them from navigation controller and make View3 your navigation controller's root view controller and when you need view1 and view2 present them as Modal View Controllers,
when you are done with them lets say; user successfully loaded the app dismiss logo screen and present Download Screen if download successful then dismiss it.
So your View3 Will be there as root view controller, lets say your at View(n) you want to go to home screen which is View3 all you need to do is call
[self.navigationController popToRootViewControllerAnimated:NO];
When you are on view(n) and want to pop to view(n-1) just use
[self.navigationController popViewControllerAnimated:YES];
good luck,
I always use this, and it will work fine in your case. In fact the following line of code is copied to my "Notes" for quick copy/paste.
Be sure to import your ViewController.h file, if not.
for (UIViewController *viewController in self.navigationController.viewControllers) {
if([viewController isKindOfClass:["your ViewController" class]]) {
[self.navigationController popToViewController:viewController animated:NO];
}
}
In the second sequence your navigation stack changes and view3 would be at index 1. so
[[self.navigationController popToViewController:[array objectAtIndex:1] animated:NO];
would be the right way of doing it.
according to your sitation use directly name of viewController
create instance of your viewController,like this
i supposed here that your viewController name is-view3Controller
View3Controller view3Controller=[[View3Controller alloc]init];
[self.navigationController popToViewController:#"view3Controller" animated:NO]
or if you are using storyboard then
View3Controller view3Controller=[self.storyboard instantiateViewControllerWithIdentifier:#"view3Controller"];
[self.navigationController popToViewController:#"view3Controller" animated:NO]
It sounds like View 2 is not being added to your view controllers array at run time, possibly because of the segue you've created.
Try removing the segue that transitions from View 1 > View 3 and pushing the user past View 2 without animating, as your application's logic requires it:
// If the user needs to skip ahead to view 3, conditionally push view 2 and view 3 without animating
[self.navigationController pushViewController:viewController2 animated:NO];
[self.navigationController pushViewController:viewController3 animated:NO];
Alternatively if you left the segue in place could you not look at the size of the UINavigationController viewControllers property and "guess" based on the size whether or not you skipped View 2? If you did then you can adjust the popToViewController method to pop to the correct index. This is, admittedly less elegant and brittle if you need to skip other views as well.
// Check length of viewController array with 'N' views (pseudo code)
if (self.navigationController.viewControllers.length == N-1)
// View 2 was ignored: pop to objectAtIndex:1
else
// View 2 was included: pop to objectAtIndex:2
If I understood you correctly, your view3 has special view controller, so you can use such code:
NSArray *VCs = [self.navigationController viewControllers];
for (UIViewController *VC in VCs)
{
if ([VC isKindOfClass:[**YOUR-VIEW-CONTROLLER** class]]) {
[self.navigationController popToViewController:VC animated:NO];
}
}
It's simple and it works!
for (UIViewController* controller in self.navigationController.viewControllers) {
if ([controller isKindOfClass:[<Your View Controller Name> class]]) {
[self.navigationController popToViewController:controller animated:YES];
return;
}
}
Go like this to a particular view controller
[self.navigationController popToViewController:[[self.navigationController viewControllers]objectAtIndex:1] animated:YES];
I have two views which use UINavigationController. I want the second view to "slide" with animation back to the first view when I tap on a custom button. (not the original in navigationbar)
Try something like this on that button action,
[self.navigationController popToViewController:aViewController animated:YES];
or
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:([self.navigationController.viewControllers count] - 2)] animated:YES];
Here aViewController represents the previous view controller. Similarly you can pop to any viewcontroller you want by using a similar code.
[self.navigationController popToRootViewControllerAnimated:YES]; will take you to the root view controller.