UIViewControllerAnimatedTransitioning まわりのメモ

とりあえずわかったことだけ。

#### 原典

* [UIViewControllerTransitioning](https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewControllerAnimatedTransitioning_Protocol/Reference/Reference.html)
* [UIViewControllerAnimatedTransitioning](https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewControllerTransitioningDelegate_protocol/Reference/Reference.html)

## やること
1. UIViewControllerAnimatedTransitioningのプロトコルを実装した実際に動きをつけるクラスを作る。(Animatorクラスとする)
1. 使用するControllerに所定のDelegateプロトコルを実装してイベントに対してAnimatorクラスを返す

## Delegate設定の注意
* viewDidLoad時ではタイミングが遅くて動かない場合がある
* 遷移元のprepareForSegueかinitWithCoder等のinit時のタイミングだと問題ない

## Animatorクラス
* UIViewControllerAnimatedTransitioningを積む

```objc:Animator.h
#import <Foundation/Foundation.h>
@interface Animator : NSObject<UIViewControllerAnimatedTransitioning>
@end
```

* duration(アニメーション時間)返し

```objc:Animator.m
#pragma mark duration
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
    return 1.0;
}
```

* transition実装

```objc:Animator.m
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext
{
    //containerViewに遷移元と遷移先のViewを取得して入れる
    UIViewController *fromVC = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    UIViewController *toVC = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIView *containerView = [transitionContext containerView];
    [containerView insertSubview:toVC.view belowSubview:fromVC.view];
    
    //適当にアニメーション
    [UIView animateWithDuration:[self transitionDuration:transitionContext]
                     animations:^{
                         fromVC.view.alpha = 0.0;
                     }
                     completion:^(BOOL finished){
                         fromVC.view.alpha = 1.0;
                         toVC.view.alpha = 1.0;
                         //終了を通知
                         [transitionContext completeTransition:YES];
                     }];
}

```

## Pushの場合

* NavigationControllerにUINavigationControllerDelegateを実装
* self.delegate=selfの設定
* Animatorクラスを返す関数を実装

```objc:
- (id<UIViewControllerAnimatedTransitioning>)
navigationController:(UINavigationController *)navigationController
animationControllerForOperation:(UINavigationControllerOperation)operation
fromViewController:(UIViewController*)fromVC
toViewController:(UIViewController*)toVC
{
    Animator* animator = [[Animator alloc] init];
    switch (operation) {
        case UINavigationControllerOperationPush:
            return animator;
            break;
        case UINavigationControllerOperationPop:
            return animator;
            break;
        case UINavigationControllerOperationNone:
        default:
            break;
    }
    return nil;
}
```

## Modalの場合

* 遷移先(Modalするやつ)にUIViewControllerTransitioningDelegateを実装する
* self.transitioningDelegate=selfの設定
* Animatorクラスを返す関数を実装

```objc:
- (id <UIViewControllerAnimatedTransitioning>)animationControllerForPresentedController:(UIViewController *)presented
                                                                   presentingController:(UIViewController *)presenting
                                                                       sourceController:(UIViewController *)source
{
    return [[Animator alloc] init];
}

- (id <UIViewControllerAnimatedTransitioning>)animationControllerForDismissedController:(UIViewController *)dismissed
{
    return [[Animator alloc] init];
}
```

## UITabbarController

* UITabBarControllerにUITabBarControllerDelegateを実装する。
* self.delegate=selfの設定
* Animatorクラスを返す関数を実装する

```objc:
- (id<UIViewControllerAnimatedTransitioning>)tabBarController:(UITabBarController *)tabBarController
           animationControllerForTransitionFromViewController:(UIViewController *)fromVC
                                             toViewController:(UIViewController *)toVC
{
    //segueでTabBarControllerに遷移してくる場合、初期表示はfromVC無いので分岐する
    if(fromVC){
        return [[Animator alloc] init];
    }else{
        return nil;
    }
}
```