Ios – Is transitionFromViewController just a convenience method in iOS

iosios5iphoneuiviewcontroller

I'm not sure I understand what transitionFromViewController:toViewController:duration:options:animation:completion: does exactly. Is it just a convenience method?

For instance, what's the difference between doing this…

[self transitionFromViewController:fromViewController
                  toViewController:toViewController
                          duration:0.25
                           options:UIViewAnimationOptionCurveEaseInOut
                        animations:^{
                            fromViewController.view.alpha = 0;
                            toViewController.view.alpha = 1;
                        } completion:^(BOOL finished) {
                            [fromViewController removeFromParentViewController];
                            [toViewController didMoveToParentViewController:self];
                        }];

…and this?

[self.view addSubview:toViewController.view];
[UIView animateWithDuration:0.25
                      delay:0
                    options:UIViewAnimationOptionCurveEaseOut
                 animations:^{
                     fromViewController.view.alpha = 0;
                     toViewController.view.alpha = 1;
                 } completion:^(BOOL finished){
                     [fromViewController.view removeFromSuperview];
                     [fromViewController removeFromParentViewController];
                     [toViewController didMoveToParentViewController:self];
                 }];

The reason I ask is that in some cases I need to add the child controller view to a specific subview of the container controller view. Using transitionFromViewController:toViewController:duration:options:animation:completion: does not give me this option.

Best Answer

Yes, I think you're right: They appear to be functionally the same (not sure we can call it a convenience method without knowing the details of the implementation, but could well be). Obviously, transitionFromViewController is designed for view controller containment and animateWithDuration is designed a general purpose animation of views.

Given that you're obviously doing containment, one probably should use transitionFromViewController rather than animateWithDuration. It's unambiguous and the technique recommended by Apple. And if you have the fromViewController.view in a subview, the new toViewController.view will be added to the same subview.

I'd also suggest including the missing willMoveToParentViewController and addChildViewController (which I assume you omitted for the sake of brevity, but I include for the sake of completeness):

[fromViewController willMoveToParentViewController:nil];
[self addChildViewController:toViewController];

[self transitionFromViewController:fromViewController
                  toViewController:toViewController
                          duration:0.25
                           options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionCrossDissolve
                        animations:^{}
                        completion:^(BOOL finished){
                            [fromViewController removeFromParentViewController];
                            [toViewController didMoveToParentViewController:self];
                        }];

Also note that I'm using UIViewAnimationOptionTransitionCrossDissolve. If you're setting alphas manually, don't forget to initialize the toViewController.view.alpha, e.g.:

[fromViewController willMoveToParentViewController:nil];
[self addChildViewController:toViewController];
toViewController.view.alpha = 0.0;

[self transitionFromViewController:fromViewController
                  toViewController:toViewController
                          duration:0.25
                           options:UIViewAnimationOptionCurveEaseInOut
                        animations:{
                            fromViewController.view.alpha = 0.0;
                            toViewController.view.alpha = 1.0;
                        }
                        completion:^(BOOL finished){
                            [fromViewController removeFromParentViewController];
                            [toViewController didMoveToParentViewController:self];
                        }];
Related Topic