在模态呈现中使用 [UIViewControllerTransitionCoordinator animateAlongsideTransition:completion:] 时,不会调用动画块

When using [UIViewControllerTransitionCoordinator animateAlongsideTransition:completion:] in a modal presentation, the animation block is not called

我有一个 UIViewController,它通过故事板中的模态转场呈现(嵌入在 UINavigationController 中)。我正在尝试在模态表示的同时为键盘外观设置动画(这的逻辑超出了问题的范围)。

我在 viewWillAppear: 中使用 [self.transitionCoordinator animateAlongsideTransition:completion:] 来执行此操作,但我注意到从未调用动画块。因此,一些日志记录让我看到 只有一次 新创建的 模态视图控制器上调用动画块是在 viewDidLoad:.

@implementation MyModalViewController

- (void)viewDidLoad {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    [super viewDidLoad];

    [self.transitionCoordinator animateAlongsideTransition:^ (id <UIViewControllerTransitionCoordinatorContext> context) {
        NSLog(@"%s ANIMATION", __PRETTY_FUNCTION__);
    } completion:^ (id <UIViewControllerTransitionCoordinatorContext> context) {
        NSLog(@"%s COMPLETION", __PRETTY_FUNCTION__);
    }];
}

- (void)viewWillAppear:(BOOL)animated {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    [super viewWillAppear:animated];

    [self.transitionCoordinator animateAlongsideTransition:^ (id <UIViewControllerTransitionCoordinatorContext> context) {
        NSLog(@"%s ANIMATION", __PRETTY_FUNCTION__);
    } completion:^ (id <UIViewControllerTransitionCoordinatorContext> context) {
        NSLog(@"%s COMPLETION", __PRETTY_FUNCTION__);
    }];
}

- (void)viewWillDisappear:(BOOL)animated {
    NSLog(@"%s", __PRETTY_FUNCTION__);
    [super viewWillDisappear:animated];

    [self.transitionCoordinator animateAlongsideTransition:^ (id <UIViewControllerTransitionCoordinatorContext> context) {
        NSLog(@"%s ANIMATION", __PRETTY_FUNCTION__);
    } completion:^ (id <UIViewControllerTransitionCoordinatorContext> context) {
        NSLog(@"%s COMPLETION", __PRETTY_FUNCTION__);
    }];
}

@end

这个控制器模态表示的输出是:

SampleAnimatedTransition[43690:1768171] -[MyModalViewController viewDidLoad]
SampleAnimatedTransition[43690:1768171] __36-[MyModalViewController viewDidLoad]_block_invoke ANIMATION
SampleAnimatedTransition[43690:1768171] -[MyModalViewController viewWillAppear:]
SampleAnimatedTransition[43690:1768171] __36-[MyModalViewController viewDidLoad]_block_invoke_2 COMPLETION
SampleAnimatedTransition[43690:1768171] __40-[MyModalViewController viewWillAppear:]_block_invoke_2 COMPLETION

但是在解雇期间输出是:

SampleAnimatedTransition[43690:1768171] -[MyModalViewController viewWillDisappear:]
SampleAnimatedTransition[43690:1768171] __43-[MyModalViewController viewWillDisappear:]_block_invoke ANIMATION
SampleAnimatedTransition[43690:1768171] __43-[MyModalViewController viewWillDisappear:]_block_invoke_2 COMPLETION

注意动画块在 viewWillAppear: 中是如何不被调用的,更令人讨厌的是 viewDidLoad: 中的动画块在 [=17= 之前被调用] 根本没有被调用。

任何人都可以帮我得到要调用的动画块viewWillAppear:吗?

请注意,当我将另一个视图控制器推到导航控制器上并返回时,viewWillAppear:中的动画块被调用。

如果有帮助,我做了一个Sample Project

更新

这已被归档为 rdar://20171073

您正在展示 UINavigationController。您可以通过子类化 UINavigationController 并覆盖 -viewWillAppear: 来为该演示文稿制作动画。但是,此时导航控制器尚未将其根视图控制器添加到视图层次结构中,因此您设置的任何动画都将不起作用。

@implementation MyNavigationController
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.transitionCoordinator animateAlongsideTransition:^ (id <UIViewControllerTransitionCoordinatorContext> context) {
        NSAssert([self.viewControllers[0] superview] != nil, @""); // Fails
    } completion:nil];
}
@end

事实证明,您可以使用 layoutIfNecessary:

强制 UINavigationController 设置其视图层次结构
@implemenation MyNavigationController
- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.view layoutIfNeeded];
}
@end

这还负责在根视图控制器上调用 -viewWillAppear:,使您可以使用模态呈现进行动画处理。

通过这个 hack,我可以在模态演示中添加动画。它很难看,我不会使用它,但它至少可以让你测试你的键盘动画方法是否有任何优点。

根据您实际想要完成的目标,您可能会更幸运地使用 UIPresentationController.

创建自定义模式演示文稿