In our iOS application with three UIViewControllers one after another, we would like to skip the middle one based on some condition and go directly from first to third. However, the user should be able to come back to the second one via the "Back" button on the third controller.
I tried [self performSegueWithIdentifier:#"segueId" sender:sender]; from viewDidLoad, viewWillAppear but this corrupts the navigation bar as indicated by the debug log. Calling this code from viewDidAppear works fine, but then the second view is already displayed, which is what I was trying to avoid in the first place.
I also tried [self.navigationController pushViewController:vc animated:NO]; but the result is similarly corrupted nav bar, even though this time debug log does not have such entries.
What would be the supported way of doing this (if it is at all possible)?
The target is iPhone4 with iOS 5.1, and the dev environment is Xcode 4.3.
I use the following code in an app. Works exactly as expected.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
SecondViewController *secondVC = [self.storyboard instantiateViewControllerWithIdentifier:#"DetailViewController"];
if (indexPath.row == 0) {
// skip second vc
ThirdViewController *thirdVC = [self.storyboard instantiateViewControllerWithIdentifier:#"ThirdViewControllerViewController"];
[self.navigationController pushViewController:secondVC animated:NO];
[self.navigationController pushViewController:thirdVC animated:YES];
}
else {
// push second vc
[self.navigationController pushViewController:secondVC animated:YES];
}
}
If you want to skip a view controller you can just call UINavigationController setViewControllers:animated: It will animate to the last controller in the supplied array, and the user will be able to "back" out of that stack.
You can build up the array of view controllers any way you like; perhaps starting with the existing array of view controllers:
NSMutableArray* newViewControllers = [[navController.viewcontrollers mutablecopy] autorelease];
[newViewControllers addObject: ...];
[navController setViewControllers: newViewControllers animated: YES];
Related
I am having an app which has a UITableViewController which is my settings page. I am pushing the UITableViewController with a presentModalViewController using self.navigationController (using storyboard ID). however each time I try to see that page, it's showing exception. After reading few posts I tried implementing two methods
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [super tableView:tableView
cellForRowAtIndexPath:indexPath];
return cell;
}
**my .h File**
#interface Setting : UITableViewController<UITableViewDelegate,UITableViewDataSource>
I have done all UI settings in IB so I didn't change anything in above two implemented methods.
In mainviewcontroller from where I am pushing the view to UITableViewController, I am using the below code
Setting *nextController = [[self storyboard] instantiateViewControllerWithIdentifier:#"setting"];
[self presentModalViewController:nextController animated:YES];
Setting *dvc = [[Setting alloc] init];
[self.navigationController pushViewController:dvc animated:YES];
As I already set all UIs in IB why do I need to implement those methods? At least I can seen the view correctly.
It looks like you're trying to initialize the same viewController twice. You don't need to alloc] init] after you instantiateViewControllerWithIdentifier. At least, from my experience you don't. Try this:
Setting *nextController = [[self storyboard] instantiateViewControllerWithIdentifier:#"setting"];
[self.navigationController pushViewController:nextController animated:YES];
That will "push" the nextController with the storyBoardID of "setting" from the right into your existing NavigationController.
However, using my intuition, I believe you want to present a settings view modally, that has it's own NavigationController. In that case, try this code, which wraps the Settings ViewController into a NavigationController, and presents that whole thing modally, so you can navigate within settings:
Setting *nextController = [self.storyboard instantiateViewControllerWithIdentifier:#"setting"];
UINavigationController *navcont = [[UINavigationController alloc] initWithRootViewController:nextController];
navcont.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:navcont animated:YES completion:nil];
Alternatively, you could do all of this in the Storyboard itself. Select your settings view controller, and go to Editor Menu > Embed In... > Navigation Controller. Then make a segue from your button to the navigation controller that holds the settings controller. Set the segue to "Modal" and you're all done.
I'm trying to do a switch view. My first view is a storyboard and i want to switch for view2, i have no problem when click the botton in my first view everything is fine. The prolem is when i am trying to go back, the screen is going black and is not going back to the first view. Here the code that i'm using.
ViewController.h
- (IBAction)View2:(id)sender;
ViewController.m
- (IBAction)View2:(id)sender {
View2 *second = [[View2 alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:second animated:YES];
}
And here the code that i am using to go back from the second view to the first.
view2.h
- (IBAction)back:(id)sender;
View2.m
- (IBAction)back:(id)sender {
ViewController *second = [[ViewController2 alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:second animated:YES];
}
Am I doing some kind of error?
Thanks
Your issue is in View2.m
- (IBAction)back:(id)sender {
[self dismissModalViewControllerAnimated:YES];
}
should do the trick
Apple has a View Controller Programming Guide that I suggest skimming through
UPDATE
If you need to jump back more that one ViewController, you should use NSNotificationCenter or keep a reference to the viewController you need to jump back to.
In my experiences, the following line does 1 of 2 things (where self is a subclass of UIViewController)
[self dismissModalViewControllerAnimated:YES];
1) If self has presented another view controller, the line above will dismiss all view controllers that have been presented on top of self
2) If self has not presented any other view controller, the line above will dismiss self back to the previous view controller
There are actually three views at play. My homeView, which is where I launch the picker from, which sets the StudyPickerController view as root to a navController, which is then presented inside of the popOverController. Then from within the StudyPickerController view, I need to push to the ScreenPickerController, a different view completely.
I have a UIPopOverController that is displaying the contents of a view that is a tableView. I would like to be able to push a new view with a viewController inside of this view, but as I will discuss, it is really close, but it just won't push!
So from my homeView, when the button is pushed, an action is called and this code is run:
self.studyPicker = [[[StudyPickerController alloc] initWithStudyArray:self.studyArray ViewNum:butto.tag] autorelease];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.studyPicker];
_studyPicker.delegate = self;
self.studyPickerPopover = [[[UIPopoverController alloc] initWithContentViewController:navController] autorelease];
[self.studyPickerPopover presentPopoverFromRect:CGRectMake(120,45, 10,10) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
And this works pretty well! The popOverController displays the contents of my StudyPickerController without any problems. I get the feeling that I am indeed getting access to my navigationController because the frame of the popOverController has a bar at the top, instead of just being a thin border, it has a navigationBar.
So now when I want to select a row in this view, I would like to push to a new view, also with a tableView, with my navigationController. This is the code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray * array = [_studyArray objectAtIndex:indexPath.row];
ScreenPickerController * picker = [[ScreenPickerController alloc] init];
picker.seriesGUID = array;
picker.viewNumber = viewNumber;
[self.navigationController pushViewController:picker animated:YES];
}
It seems to me that this should be working! But alas, I press a row, and it highlights, and nothing happens.
I've been working on this all day, so it very well could be that I am just missing something, but I don't know what it is. Any help is appreciated
It seems there are two classes involved here: your homeView class and the StudyPickerController. I'm guessing the tableView:didSelectRowAtIndexPath: method would be in the homeView class?
In that case, self.navigationController is trying to access the navigation controller that homeView is in, not the navigation controller you put into the popover. Since homeView isn't even in a navigation controller, the accessor returns nil.
Instead, you will want to use something like [self.studyPicker.navigationController pushViewController:picker animated:YES];.
I'm searching a way to be able to display one modal view controller after another one, and make the second appear while the first is disapearing.
The problem is that the dismiss call that is done inside the first modalviewcontroller applies to both and SecondController is never shown.
Putting the first dismiss before or after the parent call does not change anything.
If first dismiss is set wih animate= NO, everything works fine. But I need the animation.
I planned to do that this way, but the problem is that the dismiss call that is done inside the first modalviewcontroller applies to both and SecondController is never shown.
I don't understand why because each modal view has its own navigationcontrollers, so they shouldn't collide.
I tried another way by showing the second modal view with a NSTimer after 0.5 sec, but it's not satisfying : the second appears when the first has completely disapeared. Not smooth at all... If I set the delay less than 0.5 sec, the second modal view never shows up. And using such a timer to make this does not seem to be a good way of coding.
Main.m
- (void) entry {
FirstController *nextWindow = [[FirstController alloc] initWithNibName:#"theNIB" bundle:nil];
nextWindow.caller = self;
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:nextWindow];
[self.navigationController presentModalViewController:navController animated:YES];
[nextWindow release];
[navController release];
}
- (void) thingsDoneInFirstModalController:(OBJECT)returnValue retval2:(OBJECT2)returnValue2 {
[self display2ndController];
}
- (void) display2ndController {
SecondController *nextWindow;
nextWindow = [[SecondController alloc] initWithNibName:#"NIB2" bundle:nil];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:nextWindow];
[self.navigationController presentModalViewController:navController animated:YES];
[navController release];
[nextWindow release];
}
1st ModalViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.navigationController dismissModalViewControllerAnimated:YES];
[self.caller thingsDoneInFirstModalController:theResult retval2:someMoreResult];
}
Do you know a way to make this possible (make the second view appears while the first one is disappearing), with some code for example ?
Thank you.
Try creating some dummy ViewController, and present your second one using it.
I have TabBarView Controller, where i keep four tab bar items, let sat item1, item2, item3 and item 4.
When clicking on item2 tab bar item, i call a RootViewController where it has a Navigation controller with a TableView and shows the row items.
Upto here it is fine.
When clicking on a row item, will have to launch a UIWebView to show the content.
I did code like below for this process.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
navigationController = [[UINavigationController alloc] init];
webViewController = [[WebViewController alloc] init];
[[self navigationController] pushViewController:webViewController animated:NO];
[webViewController release];
}
The problem now is, clicking on a row item is not pushing the UIWebView code at all. I tested the UIWebView code with normal addSubView method like
"[appDelegate.window addSubview:webViewController.view];"
instead of calling via pushViewController. It is calling UIWebView and shows the web content successfully.
I understand the problem should be calling as pushViewController:webViewController.
Can anyone point me what are the ways that it should be not be worked in this case and how can i correct it to make it work with pushViewController itself? I need to call UIWebView only using pushViewController.
For such all these combination, is there any sample source available?
Waiting for someone's help.
thanks.
Clave/
I think you are mistakenly creating a new navigation controller here
navigationController = [[UINavigationController alloc] init];
remove that line and use
[self.navigationController pushViewController:webViewController animated:NO];
instead of your reference above. That should do it :-)