transitionFromView:toView:duration:options:completion: is not animating the transition
Asked Answered
S

3

7

I have a view controller that displays the views of 2 sub view controllers in a given area of its view. The 2 sub view controllers are FlopVC and FipVC.

I want to animate the transition from one sub view to the other. The code I'm using is:

-(IBAction)flip:(id)sender{

    UIViewController *newVC = nil;

    if (self.isFlip) {
        newVC = [[FlopVC alloc] initWithNibName:nil bundle:nil];
    }else{
        newVC = [[FipVC alloc] initWithNibName:nil bundle:nil];
    }

    newVC.view.frame = CGRectMake(120, 20, 240, 260);
    [self.view addSubview:newVC.view];

    [UIView transitionFromView:self.currentVC.view
                        toView:newVC.view
                      duration:0.9
                       options:UIViewAnimationTransitionFlipFromLeft 
                    completion:^(BOOL finished) {
                        self.currentVC = newVC;
                        self.isFlip = ! self.isFlip;
                    }];



}

The sub views are swapped, but without any animation. What am I doing wrong?

PS the full project is here.

Seizing answered 28/10, 2011 at 22:47 Comment(0)
M
18
UIViewAnimationTransitionFlipFromLeft != UIViewAnimationOptionTransitionFlipFromLeft
Marelda answered 29/10, 2011 at 16:26 Comment(4)
I had the horrible feeling it was something stupid, but had no idea it was this bad. :-P I owe you a beer at the next @nscoder_madSeizing
Ha,ha...it was tricky, I have more stupid mistakes every week. I'll accept the beer though :)Marelda
Ruddy hell, I just made exactly the same mistake. Thank you Google + stackoverflow! :) (and madmw of course!)Swat
aaarghhhhh! interesting option naming, though ... very error-proneCiracirca
A
3

if you are using the new iOS5 view container paradigm you need to do something along the lines of the following:

-(IBAction)flip:(id)sender{

    UIViewController *newVC = nil;

    if (self.isFlip) {
       newVC = [[FlopVC alloc] initWithNibName:nil bundle:nil];
    }else{
       newVC = [[FipVC alloc] initWithNibName:nil bundle:nil];
    }

    newVC.view.frame = CGRectMake(120, 20, 240, 260);

    // required for the new viewController container
    self.currentVC willMoveToParentViewController:nil];
    [self addChildViewController:newVC];
    [self transitionFromViewController:self.currentVC
                  toViewViewController:newVC.view
                              duration:0.9
                               options: UIViewAnimationOptionTransitionFlipFromLeft 
                            animations:nil
                            completion:^(BOOL finished) {
                               // required for the new viewController container
                               [self.currentVC removeFromParentViewController];
                               [newVC didMoveToParentViewController:self];

                               self.currentVC=newVC;
                             }];



}

reference the section Implementing a Container View Controller and the 2011 WWDC videos on UIViewController containers for more info.

Approachable answered 28/10, 2011 at 23:4 Comment(5)
Regarding the "animations" parameter, the docs state "This parameter must not be NULL."Hasbeen
howdy. It's not NULL but nil and it is taken directly from Apple Sample Code. per the docs: "A block object containing the changes to commit to the views. Here you programmatically change any animatable properties of the views in your view hierarchy. This block takes no parameters and has no return value. This parameter must not be NULL." you can send nil because you can send a message to nil. You can't send a message to NULL.Approachable
Thanks for the clarification - my Java roots were showing there. :)Hasbeen
As shown in Listing 14-3 in Implementing a Custom Container View Controller, you need [oldVC willMoveToParentViewController:nil]; before the transition (otherwise you're missing a notification) and [oldVC removeFromParentViewController]; in the completion block (otherwise, the old controller is not removed from childViewControllers array).Leola
thanks for the note. I've corrected the example. The listing you cite is new since I originally answered. Thanks for the correction!Approachable
G
2

Here is working code that (by sheer coincidence) does exactly what you're describing. My two child vc's are stored in self->swappers. The integer cur keeps track of which one is currently showing. The spot in my interface where the subview is to go is marked by a view outlet, panel.

UIViewController* fromvc = [self->swappers objectAtIndex:cur];
cur = (cur == 0) ? 1 : 0;
UIViewController* tovc = [self->swappers objectAtIndex:cur];
tovc.view.frame = self.panel.bounds;

// must have both as children before we can transition between them
[self addChildViewController:tovc]; // "will" called for us
// note: when we call remove, we must call "will" (with nil) beforehand
[fromvc willMoveToParentViewController:nil];

[self transitionFromViewController:fromvc
                  toViewController:tovc
                          duration:0.4
                           options:UIViewAnimationOptionTransitionFlipFromLeft
                        animations:nil
                        completion:^(BOOL done){
                            // note: when we call add, we must call "did" afterwards
                            [tovc didMoveToParentViewController:self];
                            [fromvc removeFromParentViewController]; // "did" called for us
                        }];
Geometer answered 5/11, 2011 at 2:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.