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.
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];
}];
Short answer:
No it's not just a convenience method as the time when what appearance-method is called on both child-controllers is different.
Long answer:
Regarding -->
[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];
}];
What happens behind the scene when you call
[self.view addSubview:toViewController.view];
is something like this (of course this is not complete)
[toViewController.view viewWillAppear:false]; <-- meaning not animated
//Add the view to the view hierarchy
//Layout the view
[toViewController.view viewDidAppear:false]; <-- meaning not animated
Afterwards when you do the animation toViewController "thinks" that it's view is already visible and has been presented without an animation. The same is true for the fromViewController. During your animation the fromViewController does not know that it's view gets dismissed as viewWill/DidDisappear will be called after the animation with your call to
[fromViewController.view removeFromSuperview];
On the other hand -->
[self transitionFromViewController:fromViewController
toViewController:toViewController
duration:0.25
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionTransitionCrossDissolve
animations:^{}
completion:^(BOOL finished){
[fromViewController removeFromParentViewController];
[toViewController didMoveToParentViewController:self];
}];
does something like this
[UIView animateWithDuration:yourDuration
delay:yourDelay
options:yourOptions
animations:^{
[toViewController viewWillAppear:true];
[fromViewController viewWillDisappear:true];
//Add toViewcontroller.view to the view hierarchy
//Layout the toViewcontroller.view --> changes here are not animated. (There is no "previous state" as the view has just been added to the hierarchy)
//Call your animation-block
} completion:^(BOOL finished){
[toViewController viewDidAppear:true];
[fromViewController.view removeFromSuperview];
[fromViewController viewDidDisappear:true];
//Call your completion-block
}];
So long answer short:
viewWillAppear and viewWillDisappear are called inside the animation-block and get passed true. This may or may not be useful to your application so there may or may not be a difference between the two methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With