在模态演示中使用 [UIViewControllerTransitionCoordinator animateAlongsideTransition:completion:] 时,不调用动画块

Posted

技术标签:

【中文标题】在模态演示中使用 [UIViewControllerTransitionCoordinator animateAlongsideTransition:completion:] 时,不调用动画块【英文标题】:When using [UIViewControllerTransitionCoordinator animateAlongsideTransition:completion:] in a modal presentation, the animation block is not called 【发布时间】:2015-03-12 18:00:30 【问题描述】:

我有一个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: 中没有调用动画块,更烦人在调用viewWillAppear: 之前调用了viewDidLoad: 中的动画块。

谁能帮我获取要调用的动画块viewWillAppear:

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

如果有帮助,我发了Sample Project。

更新

已提交为rdar://20171073

【问题讨论】:

【参考方案1】:

您提交的是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

事实证明,您可以强制 UINavigationController 使用 layoutIfNecessary 设置其视图层次结构:

@implemenation MyNavigationController
- (void)viewWillAppear:(BOOL)animated

    [super viewWillAppear:animated];
    [self.view layoutIfNeeded];

@end

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

通过这个 hack,我可以在模态演示的旁边制作动画。它很丑,我不会使用它,但它至少可以让您测试您在键盘动画方面的方法是否有任何优点。

根据您实际尝试完成的任务,您可能会更幸运地使用UIPresentationController 创建自定义模式演示文稿。

【讨论】:

我要从这里创建一个雷达,绝对感觉像一个错误。正如您所说,当我直接呈现模态时,确实会调用 viewWillAppear: 动画块,但在这种情况下,viewDidLoad 中似乎未设置 [self transitionCoordinator]。嵌入到 UINavigationController 到没有时完全不同的行为。 我遇到了类似的问题,当导航回以前未出现的嵌套导航控制器时没有动画(通过在堆栈中替换或恢复状态)。我必须将 layoutIfNeeded 放在 viewDidLoad 而不是 viewWillAppear 放在导航控制器子类中。

以上是关于在模态演示中使用 [UIViewControllerTransitionCoordinator animateAlongsideTransition:completion:] 时,不调用动画块的主要内容,如果未能解决你的问题,请参考以下文章

无法在 SwiftUI 中使用 ForEach 和 CoreData 将数据正确传递给模态演示

自定义 inputView 在模态演示期间未正确设置动画

UIScrollView 在模态视图控制器的动画演示中滚动到不同的位置

隐藏在模态视图中的状态栏(在全屏演示中)

iOS 13 UIViewController 模态演示阴影

为啥模态演示表单未按预期显示?