gpt4 book ai didi

ios - 取消交互式 UINavigationController 弹出手势不会调用 UINavigationControllerDelegate 方法

转载 作者:IT王子 更新时间:2023-10-29 08:05:17 26 4
gpt4 key购买 nike

如果您拖动 UIViewController 的边缘以在 UINavigationController 中开始交互式弹出转换,当前下方的 UIViewController 具有 viewWillAppear: 被调用,然后是 UINavigationControllerDelegate 方法 navigationController:willShowViewController:animated:

如果取消转换(即被拖动的 Controller 放回原来的位置而不弹出),viewWillAppear:viewDidAppear: 会在顶 View Controller 上调用正如预期的那样,但是委托(delegate)方法 navigationController:willShowViewController:animated:navigationController:didShowViewController:animated: 不是。考虑到调用了 UIViewController View 生命周期方法,似乎至少应该调用其中一个或两个。我想知道这是故意的还是 UINavigationController 中的错误。

我真正需要的是能够在我的 UINavigationController 子类或其 UINavigationControllerDelegate 中看到交互式 pop 何时被取消。有没有明显的方法可以做到这一点?

编辑

我仍在寻找解决方案,但我想提一下,我已将此问题报告为 Apple 的错误。查看文档,没有理由不调用这些委托(delegate)方法,尤其是考虑到确实调用了等效的 View 生命周期方法。

edit2

我的雷达票 (16823313) 今天(2015 年 5 月 21 日)关闭并标记为预期。 :(

Engineering has determined that this issue behaves as intended based on the following information:

This is actually the correct behavior. The navigation transition that's happening from B -> A, if you cancel it mid-transition, you won't get the didShowViewController: method. A cancellation of this transition shouldn't be considered a transition from A -> B because you never actually reached A.

view[Will/Did]Appear should still be called as expected too.

这种情况非常令人失望,因为它违反直觉,但我下面的回答中的解决方法在可预见的 future 应该可以正常工作,至少对于我的用例而言。

最佳答案

对于任何感兴趣的人,我发现了两种在 UINavigationControllerDelegate 级别解决此问题的方法。

  1. 使用 KVO 观察 interactivePopGestureRecognizerstate 属性。不幸的是,取消转换不会将状态更改为 UIGestureRecognizerStateFailed,而只是更改为 UIGestureRecognizerStateEnded,因此您需要编写一些额外的代码来跟踪发生的情况,如果您需要区分取消或完成的 pop。

  2. 经过测试,这可能是更好的解决方案:使用 navigationController:willShowViewController:animated: 方法向转换协调器添加通知 block 。它看起来像这样:

    - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
    [[self transitionCoordinator] notifyWhenInteractionEndsUsingBlock:^(id<UIViewControllerTransitionCoordinatorContext> context)
    {
    if([context isCancelled])
    {
    UIViewController *fromViewController = [context viewControllerForKey:UITransitionContextFromViewControllerKey];
    [self navigationController:navigationController willShowViewController:fromViewController animated:animated];

    if([self respondsToSelector:@selector(navigationController:didShowViewController:animated:)])
    {
    NSTimeInterval animationCompletion = [context transitionDuration] * (double)[context percentComplete];

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((uint64_t)animationCompletion * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    [self navigationController:navigationController didShowViewController:fromViewController animated:animated];
    });
    }


    }
    }];
    }

一开始我对使用这个解决方案犹豫不决,因为文档不清楚你是否可以设置多个(因为在那种情况下,如果一个不知情的 View Controller 也设置了自己的通知 block ,它可能要么替换这个,要么被这个替换)。不过在测试之后,它似乎不是 1:1 的关系,您可以安全地添加多个通知 block 。

编辑

我编辑了上面的代码以延迟 navigationController:didShowViewController:animated: 调用,使其仅在动画应该完成以更接近预期的默认行为时调用。

关于ios - 取消交互式 UINavigationController 弹出手势不会调用 UINavigationControllerDelegate 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23484310/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com