首页 > 解决方案 > 取消自定义视图控制器转换后执行解除完成回调

问题描述

我正在尝试构建一个自定义视图控制器转换,它与这些 API 交互且可中断:

我想要实现的是我可以模态地呈现一个视图控制器,然后UIPanGestureRecognizer通过向下拖动它来关闭呈现的视图控制器。如果我在屏幕上半部分松开手指,则应取消过渡,否则过渡将成功完成。

这是有关该问题的代码:

    func handlePanGesture(gestureRecognizer: UIPanGestureRecognizer) {
        let translation = gestureRecognizer.translation(in: presentedViewController.view)
        switch gestureRecognizer.state {
        case .began:
            interacting = true
            presentingViewController.dismiss(animated: true) {
                print("Dismissal Completion Callback is Called.")
                // How can I know the dismissal is successful or cancelled.
            }
        case .changed:
            let fraction = (translation.y / UIScreen.main.bounds.height)
            update(fraction)
        case .ended, .cancelled:
            interacting = false
            if (percentComplete > 0.5) {
                finish()
            } else {
                cancel()
            }
        default:
            break
        }
    }

我的代码在 UI 和交互方面效果很好,但我不理解 function 的行为func dismiss(animated flag: Bool, completion: (() -> Void)? = nil)

在 , 的.began情况下Pan GesturepresentingViewController.dismiss(animated: true) { ... }调用,所以自定义转换开始。但completion无论解雇转换是否取消,回调总是被调用。

我观看了 WWDC 的这些视频:

在此处输入图像描述

他们使用示例代码来演示使用 UINavigationController 的自定义转换,并且没有提及解除回调。

presentingViewController.dismiss(animated: true) {
        debugPrint("Dismissal Completion Called")
        debugPrint("[ presentedViewController.transitionCoordinator?.isCancelled \(self.presentedViewController.transitionCoordinator?.isCancelled) ]")
}

在有关completion参数的文档中:

完成

视图控制器关闭后要执行的块。这个块没有返回值,也没有参数。您可以为此参数指定 nil。

问题

Completion因为它总是在自定义转换被取消或完成后调用 ,真正的含义是什么?</p>

当我使用带有演示和关闭的自定义转换时,处理真正的关闭完成以更新 UI 和数据的最佳实践是什么?</p>

标签: ios

解决方案


经过一些研究和测试 - 是的,我会说这有点令人困惑。

关闭 VC 后不会调用完成块。而是在函数返回后调用它。

因此,假设您正在实现UIPercentDrivenInteractiveTransition.dismiss()触发您的转换代码,并在您cancel()或时返回finish()- 但它的完成块不知道您对转换实际做了什么。

我确信有多种方法可以解决此问题……但我的第一个想法是将您的“完成代码”放在case .ended, .cancelled:您(已经)确定是否删除 VC(是否调用.cancel().finish())的位置。


推荐阅读