2015-07-16 4 views
1

Итак, я начал работать с созданием пользовательских переходов push/pop и все работает для первого перехода push, но когда я пытаюсь нажать другой контроллер представления, я вообще не получаю анимации.Проблемы с UINavigationControllerDelegate и UIViewControllerAnimatedTransitioning

Here is a sample project with the code

Много кода входящие:

Вот мой UINavigationControllerDelegate класс:

@interface CKMNavigationControllerDelegate : NSObject <UINavigationControllerDelegate> 

- (instancetype)initWithForwardTransitionObject:(id<UIViewControllerAnimatedTransitioning>)inForwardTransitionObject popTransitionObject:(id<UIViewControllerAnimatedTransitioning>)inBackTransitionObject; 

@property(nonatomic, strong) id<UIViewControllerAnimatedTransitioning> forwardTransitionObject; 
@property(nonatomic, strong) id<UIViewControllerAnimatedTransitioning> backTransitionObject; 

@end 

@implementation CKMNavigationControllerDelegate 

- (instancetype)initWithForwardTransitionObject:(id<UIViewControllerAnimatedTransitioning>)inForwardTransitionObject popTransitionObject:(id<UIViewControllerAnimatedTransitioning>)inBackTransitionObject 
{ 
    NSAssert([inForwardTransitionObject conformsToProtocol:@protocol(UIViewControllerAnimatedTransitioning)], @"inForwardTransitionObject does not conform to protocol UIViewControllerAnimatedTransitioning"); 
    NSAssert([inBackTransitionObject conformsToProtocol:@protocol(UIViewControllerAnimatedTransitioning)], @"inBackTransitionObject does not conform to protocol UIViewControllerAnimatedTransitioning"); 

    self = [super init]; 
    if(!self) return nil; 

    _forwardTransitionObject = inForwardTransitionObject; 
    _backTransitionObject = inBackTransitionObject; 

    return self; 
} 

- (void)setForwardTransitionObject:(id<UIViewControllerAnimatedTransitioning>)inForwardTransitionObject 
{ 
    NSAssert([inForwardTransitionObject conformsToProtocol:@protocol(UIViewControllerAnimatedTransitioning)], @"inForwardTransitionObject does not conform to protocol UIViewControllerAnimatedTransitioning"); 
    _forwardTransitionObject = inForwardTransitionObject; 
} 

- (void)setBackTransitionObject:(id<UIViewControllerAnimatedTransitioning>)inBackTransitionObject 
{ 
    NSAssert([inBackTransitionObject conformsToProtocol:@protocol(UIViewControllerAnimatedTransitioning)], @"inBackTransitionObject does not conform to protocol UIViewControllerAnimatedTransitioning"); 
    _backTransitionObject = inBackTransitionObject; 
} 

- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)inNavigationController animationControllerForOperation:(UINavigationControllerOperation)inOperation fromViewController:(UIViewController *)inFroViewController toViewController:(UIViewController *)inToViewController 
{ 
    return inOperation == UINavigationControllerOperationPush ? self.forwardTransitionObject : self.backTransitionObject; 
} 

Мой класс, который реализует UIViewControllerAnimatedTransitioning для кнопочных переходов:

@interface CKMForwardTransitionObject : NSObject <UIViewControllerAnimatedTransitioning> 

@end 

@implementation CKMForwardTransitionObject 

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext { 
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; 
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; 

    NSAssert([toViewController conformsToProtocol:@protocol(CKMTransitionAnimatable)], @"toViewController does not conform to CKMTransitionAnimatable"); 
    NSAssert([fromViewController conformsToProtocol:@protocol(CKMTransitionAnimatable)], @"fromViewController does not conform to CKMTransitionAnimatable"); 

    id <CKMTransitionAnimatable> fromAnimationSource = (id <CKMTransitionAnimatable>)fromViewController; 
    id <CKMTransitionAnimatable> toAnimationSource = (id <CKMTransitionAnimatable>)toViewController; 

    CGFloat duration = [fromAnimationSource transitionOutDuration] + [toAnimationSource transitionInDuration]; 

    return duration; 
} 

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext 
{ 
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; 
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; 

    NSAssert([toViewController conformsToProtocol:@protocol(CKMTransitionAnimatable)], @"toViewController does not conform to CKMTransitionAnimatable"); 
    NSAssert([fromViewController conformsToProtocol:@protocol(CKMTransitionAnimatable)], @"fromViewController does not conform to CKMTransitionAnimatable"); 

    UIView *containerView = [transitionContext containerView]; 
    [containerView addSubview:toViewController.view]; 
    [containerView addSubview:fromViewController.view]; 

    id <CKMTransitionAnimatable> fromAnimationSource = (id <CKMTransitionAnimatable>)fromViewController; 
    id <CKMTransitionAnimatable> toAnimationSource = (id <CKMTransitionAnimatable>)toViewController; 


    CGFloat animationDelay = [fromAnimationSource transitionOutDuration]; 
    [fromAnimationSource animateOnTransitionOut:nil]; 

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(animationDelay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 

     [toAnimationSource animateOnTransitionIn:^{ 
      [transitionContext completeTransition:YES]; 
     }]; 
    }); 

} 

Мой протокол Tha т ViewControllers с использованием пользовательских переходов будет осуществлять:

typedef void (^CKMAnimationCompletionBlock)(void); 

@protocol CKMTransitionAnimatable <NSObject> 

- (void)animateOnTransitionIn:(CKMAnimationCompletionBlock)inAnimationCompletionBlock; 
- (void)animateOnTransitionOut:(CKMAnimationCompletionBlock)inAnimationCompletionBlock; 
- (NSTimeInterval)transitionInDuration; 
- (NSTimeInterval)transitionOutDuration; 

@end 

И, наконец, код в контроллере представления, который фактически реализует протокол CKMTransitionAnimatable:

- (NSTimeInterval)transitionInDuration 
{ 
    return 0.4; 
} 

- (NSTimeInterval)transitionOutDuration 
{ 
    return 0.4; 
} 

- (void)animateOnTransitionOut:(CKMAnimationCompletionBlock)inAnimationCompletionBlock 
{ 
    [UIView animateWithDuration:[self transitionOutDuration] animations:^{ 
     self.contentView.alpha = 0; 
    } completion:^(BOOL finished) { 
     if(inAnimationCompletionBlock) 
     { 
      inAnimationCompletionBlock(); 
     } 
    }]; 
} 

- (void)animateOnTransitionIn:(CKMAnimationCompletionBlock)inAnimationCompletionBlock 
{ 
    [UIView animateWithDuration:[self transitionInDuration] animations:^{ 
     self.contentView.alpha = 1; 
    } completion:^(BOOL finished) { 
     if(inAnimationCompletionBlock) 
     { 
      inAnimationCompletionBlock(); 
     } 
    }]; 
} 

Все выглядит довольно просто, но для жизни меня, я не вижу, что я делаю неправильно.

ответ

1

Выяснено, что проблема ... похоже, что я добавлял контроллеры представления в вид контейнера в animateTransition. Это должно выглядеть так:

- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext 
{ 
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; 
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; 

    NSAssert([toViewController conformsToProtocol:@protocol(CKMTransitionAnimatable)], @"toViewController does not conform to CKMTransitionAnimatable"); 
    NSAssert([fromViewController conformsToProtocol:@protocol(CKMTransitionAnimatable)], @"fromViewController does not conform to CKMTransitionAnimatable"); 

    UIView *containerView = [transitionContext containerView]; 
    [containerView addSubview:fromViewController.view]; 


    id <CKMTransitionAnimatable> fromAnimationSource = (id <CKMTransitionAnimatable>)fromViewController; 
    id <CKMTransitionAnimatable> toAnimationSource = (id <CKMTransitionAnimatable>)toViewController; 

    [fromAnimationSource animateOnTransitionOut:nil]; 
    CGFloat animationDelay = [fromAnimationSource transitionOutDuration]; 
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(animationDelay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
     [containerView addSubview:toViewController.view]; 
     [toAnimationSource animateOnTransitionIn:^{ 
      [transitionContext completeTransition:YES]; 
     }]; 
    }); 

} 
Смежные вопросы