Reputation: 770
I am trying to create a push segue animation where the sourceVC drops down off screen vertically and the destinationVC appears upwards onto the screen vertically. My custom segue seems to almost make this animation, however, upon the destinationVC appearing the animation does not work. Here is my -perform segue.
-(void)perform
{
UIViewController *sourceVC = self.sourceViewController;
UIViewController *destVC = self.destinationViewController;
[sourceVC.view addSubview:destVC.view];
float width = sourceVC.view.frame.size.width;
float height = sourceVC.view.frame.size.height;
destVC.view.frame = CGRectMake(0, 560, width, height);
[UIView animateWithDuration:.2 delay:0 options:UIViewAnimationOptionCurveLinear
animations:^{
[destVC.view removeFromSuperview];
sourceVC.view.frame = CGRectMake(0, 560, width, height);
} completion:^(BOOL finished) {
[UIView animateWithDuration:.2 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
destVC.view.frame = CGRectMake(0, 0, destVC.view.frame.size.width, destVC.view.frame.size.height);
} completion:^(BOOL finished) {
[sourceVC.navigationController pushViewController:destVC animated:NO];
}];
}];
}
The second animation is the one that is not working.
Any ideas what is wrong with my code? Thanks for any help.
Upvotes: 3
Views: 1853
Reputation: 770
I needed to create a custom Animator class that conformed to UIViewControllerAnimatedTransitioning.
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface SAAnimator : NSObject <UIViewControllerAnimatedTransitioning>
@end
I then implemented the required methods.
@implementation SAAnimator
-(NSTimeInterval)transitionDuration:(id<UIViewControllerContextTransitioning>)transitionContext
{
return 0.2;
}
-(void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
fromViewController.view.userInteractionEnabled = NO;
[[transitionContext containerView]addSubview:fromViewController.view];
[[transitionContext containerView]addSubview:toViewController.view];
toViewController.view.frame = CGRectMake(0, 560, toViewController.view.frame.size.width, toViewController.view.frame.size.height);
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionCurveLinear animations:^{
fromViewController.view.frame = CGRectMake(0, 560, fromViewController.view.frame.size.width, fromViewController.view.frame.size.height);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.2 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
toViewController.view.frame = CGRectMake(0, 0, toViewController.view.frame.size.width, toViewController.view.frame.size.height);
} completion:^(BOOL finished) {
[transitionContext completeTransition:YES];
}];
}];
}
@end
Then very simply, in my view controller performing the push segue, I made the class conform to the UINavigationControllerDelegate and implement this method.
#pragma mark - Animated Transiton
-(id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
{
if (operation == UINavigationControllerOperationPush) {
SAAnimator * animator = [SAAnimator new];
return animator;
}
return nil;
}
In prepareForSegue set the navigation controller's delegate
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@"toCreateVC"]) {
self.navigationController.delegate = self;
}
}
Upvotes: 3