2

Man I must say if it wasn't for this site, I would have no hair and I would've probably jumped off of a bridge right now. OK! My problem:

I'm using storyboard with xcode 4.4. I have a 3 view controllers (well 5 really but the others i THINK are irrelevant). View controller A pushes to view controller B. View controller B has a segmented control on its nav bar with 2 segments and a back button.View contoller B loads with segment 1 selected. When user selects segment 0, view controller C is then instantiated. All well and good on the first push. You get pushed to B from A, and can then when you press back it pops to A. My problem is when I popToViewController to an array list containing view controller A, it pops, but it doesnt animate! I know what you're thinking, "Animate:YES dummy!" However, animated IS yes..HUH? Here's my code:

heres whats goin on in view controller B

-(IBAction)Previous:(id)sender{
[self.navigationController popViewControllerAnimated:YES];
}

- (IBAction)segmentSwitch:(id)sender;
{
if ([sender selectedSegmentIndex] == 0)
{
    MapViewController *controller = [self.storyboard           instantiateViewControllerWithIdentifier:@"Map"];
    [self.navigationController pushViewController:controller animated:NO];
}
else if ([sender selectedSegmentIndex] == 1) {
    ListViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"List"];
    [self.navigationController pushViewController:controller animated:NO];

}
}

heres view controller C

-(IBAction)Previous:(id)sender
{
NSInteger index = -1;

ReportAppDelegate *appDelegate =
(ReportAppDelegate *)[[UIApplication sharedApplication]delegate];
MainOrangeTestViewController *orangeViewController = [appDelegate orangeViewController];

orangeViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"Orange"];
NSArray* newVCarray = [[NSArray alloc] initWithObjects:orangeViewController, nil];
self.navigationController.viewControllers = newVCarray;

for(int i=0 ; i<[newVCarray count] ; i++)
{

    if([[newVCarray objectAtIndex:i] isKindOfClass:NSClassFromString(@"MainOrangeTestViewController")])
    {
        index = i;
    }
}
[self.navigationController popToViewController:[newVCarray objectAtIndex:index] animated:YES];



}
- (IBAction)segmentSwitch2:(id)sender; {
if ([sender selectedSegmentIndex] == 0)
{
    MapViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"Map"];
    [self.navigationController pushViewController:controller animated:NO];
}
else if ([sender selectedSegmentIndex] == 1)
{
   ListViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:@"List"];
    [self.navigationController pushViewController:controller animated:NO];
}
}

I know when you instantiate you are creating a new instance of that view controller as well as creating a new nav stack (or something like that). I'm thinking that might have something to do with it. Regardless, why on earth is it not animating the pop? I'm hoping to implement something in my current build, however if it requires a rebuild then so be it! Any help is greatly appreciated. I've definitely done my homework on this one however no solution.

Thanks to all in advance!

EDIT: I should add that the initial POP back to A from view controller B is animated. HOwever when you start to toggle the segmented controls AND when you toggle to view contrller C, going back to view controller A doesn't animate the pop. So initially when you load to B from A it pops back with successful animation. But after the toggle it pops back to A with no animation and the animated method is YES.

mafiOSo
  • 183
  • 2
  • 13

2 Answers2

0

Are you just trying to push A->B->C and then pop back to A again, skipping B? If so, there's no need to modify the navigation controller's viewControllers property.

// in vcC.m ...

-(IBAction)Previous:(id)sender
{
    [self.navigationController popToRootViewControllerAnimated:YES];
}

Check out the different varieties of pop in the class reference. You can pop back one, or pop to the root, or pop to a particular VC that's in your history. The way to do that is to read the viewControllers stack (not write it), find the the VC you want to pop to, then use the popTo... method that's in your code.

But it sounds like popToRoot is what you'll need.

danh
  • 62,181
  • 10
  • 95
  • 136
  • I do apologize, I should've explained a little better. I took view A out of context. There's actually a root view controller that pushes to view controller A. So with that said, popToRoot pops to the root D: I tried poping to a specific view controller as well. However, when I toggle the segmented control, I'm instantiating a new view controller every time as per above. Doesn't that mean that I actually re-create the view controller stack or lose the stack order or something? I say that because if you toggle the segment and you press back on view controller B, it pops you to view controller A – mafiOSo Sep 19 '12 at 08:46
  • I'm sorry. I mean when you toggle the segment (which is a switch between B and C) and you press the back button when you are on B, it pops you to view controller C. Whereas if you just pushed to B from A and then press back whilst youre on B, it pops you to back to A! ....I've gone cross eyed. So what I'm getting at is, isn't the history erased once view controllers are instantiated? – mafiOSo Sep 19 '12 at 08:55
  • So I'm trying to accomplish a successful pop to A from the B and C segment. I am doing this successfully, however the pop back to A for some reason is not animating. I'm going to attempt to create a custom push segue from the segment control in view B to view C.I'll see if i can't do something like "if segmented control is on index 0 (because it starts on 1) then push to view C" and then just make both views pop to A somehow. Maybe then I can avoid instantiating and keep some history in the nav stack... Is that dumb? Sorry I'm so new at this. – mafiOSo Sep 19 '12 at 09:01
  • LOL that worked poorly. Apparently segmented control only seems to like the valueChanged event. I believe my overall problem that view C is not connected to the storyboard (hence all the instantiating). If I could somehow connect it using to the rest of the storyboard so I can have that nav stack history! I believe instantiating is screwing me up here. @danh - You totally shed some light on things man thank you so very much. Read and not write! I need to find someway to simply add view c to the history as opposed to creating new history! Any ideas would be great! :D – mafiOSo Sep 19 '12 at 12:02
0

Still a little confused about your situation, but here's another tip: You can create history beforehand. Let's say you want to push from VC0 to VC2, and when popping, you want to pop from VC2 to either VC1 or to VC0. Totally doable:

// in VC0.m, animated push to VC2
// push to vc1 invisibly
[self.navigationController pushViewController:vc1 animated:NO];
// we've made history!  now push visibly to vc2
[self.navigationController pushViewController:vc2 animated:YES];

To choose where to pop back...

// in VC2.m
if (/* user needs a regular pop back to VC1 */) {
    [self.navigationController popViewControllerAnimated:YES];
} else // pop back two, to VC0
    NSArray *viewControllers = [self.navigationController viewControllers];

    // we're not assuming that vc0 is the root here, the top of the navigation stack
    // is at index=count-1.  self is at the top.  a regular pop is just below == count-2.
    // two pops is at count-3, and so on.
    NSInteger backBackIndex = viewControllers.count - 3;

    // in case we get here by some other pushing path, worst case pop is to the root
    backBackIndex = MAX(backBackIndex, 0);

    UIViewController *backBackVC = [viewControllers objectAtIndex:backBackIndex];
    [self.navigationController popToViewController:backBackVC animated:YES];
}
danh
  • 62,181
  • 10
  • 95
  • 136
  • you're teasing me! lol... I believe my solution lies within the line that comes before the "[self.navigationController pushViewController:vc1 animated:NO];" I say this because if I've done my homework correctly (between dev docs and this AMAZING site) the best way to go about initializing a VC object on a storyboard is to instantiate it. Well therein lies the problem as well. If I instantiate, I make no history.You try and pop from an instantiated VC and xcode yells at you saying you are trying to pop to a vc that doesnt exist.Instantiating has proven to be evil in my scenario D: – mafiOSo Sep 20 '12 at 03:04
  • It may be a terminology problem, "instantiate" is what you ask a class to do to give you an instance. This allocates the object. You must instantiate a view controller for it to exist. Then you initialize it, then you present it, often by telling a container view controller (like a navigationController) to push it. – danh Sep 20 '12 at 03:09
  • Ok well I take that back. Instantiating DOES create history however it's new history. History that no longer involves VC 0, just VC 1 and 2. So when you pop from say VC 2, it takes you to VC 1 when what I'm trying to accomplish is a pop to VC 0 from both VC 1 and VC 2 (which are my segments). I have accomplished this via instantiation however it's not animating the pop transition even though the animated method is set to YES. I need a storyboard version of initWithNibName D: I don't want to be forced to nib everything theres so many VCs in my project lol help T_T – mafiOSo Sep 20 '12 at 03:22
  • so you're saying that after the "[self.storyboard instantiateViewControllerWithIdentifier:..." I can then do something like " vc = [[VC alloc]] init (somehow?)" What would be a proper way to initialize the object after instantiation? initWithNibName:nil Bundle:nil? I try that it gives me a black screen. However I have not tried that yet with an instantiation before it. Is that what you're thinking? – mafiOSo Sep 20 '12 at 03:26