取消自定义视图控制器转换后,执行解雇完成回调

时间:2019-07-10 10:43:47

标签: ios

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

  • UIViewControllerAnimatedTransitioning
  • UIPercentDrivenInteractiveTransition
  • UIViewControllerTransitioningDelegate
  • UIViewPropertyAnimator

我想要实现的是,我可以模态呈现视图控制器,然后使用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和交互方面表现出色,但我不了解函数func dismiss(animated flag: Bool, completion: (() -> Void)? = nil)的行为。

.began的{​​{1}}情况下,将调用Pan Gesture,因此自定义过渡开始。但是presentingViewController.dismiss(animated: true) { ... }回调始终被称为“无”,解雇转换是否被取消。

我观看了WWDC的这些视频:

enter image description here

他们使用示例代码来演示如何通过UINavigationController进行自定义转换,并且没有提及解雇回调。

completion

在有关presentingViewController.dismiss(animated: true) { debugPrint("Dismissal Completion Called") debugPrint("[ presentedViewController.transitionCoordinator?.isCancelled \(self.presentedViewController.transitionCoordinator?.isCancelled) ]") } 参数的文档中:

  

完成

     

关闭视图控制器后要执行的块。该块没有返回值,并且不带参数。您可以为此参数指定nil。

问题

completion的真正含义是什么,因为它总是在取消或结束自定义转换后才调用?

当我使用自定义过渡进行演示和解雇时,处理真正的解雇完成以更新UI和数据的最佳实践是什么?

2 个答案:

答案 0 :(得分:0)

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

关闭VC后,将调用 NOT (完成)块。而是在函数返回后称为

因此,假设您正在实现UIPercentDrivenInteractiveTransition.dismiss()会触发您的过渡代码,并在您cancel()finish()时返回-但其完成块不了解您实际上对过渡做了什么。

我敢肯定有多种解决方法...但是我的第一个想法是将您的“完成代码”放在case .ended, .cancelled:中,您已经(已经)确定是否删除VC (无论是致电.cancel()还是.finish())。

答案 1 :(得分:0)

最后,我在Apple文档中发现了一些有用的东西

  

在过渡动画结束时,至关重要的是调用completeTransition:方法。调用该方法将告诉UIKit过渡已完成,并且用户可以开始使用显示的视图控制器。调用该方法还会触发一系列其他完成处理程序,包括presentViewController:animated:completion:方法中的一个和动画师对象自己的animationEnded:方法中的一个。调用completeTransition:方法的最佳位置是动画块的完成处理程序中。

     

由于可以取消转换,因此应该使用上下文对象的transitionWasCancelled方法的返回值来确定需要进行的清理。取消演示后,动画设计师必须撤消对视图层次结构所做的任何修改。成功解雇需要采取类似的行动。

因此present(_:animated:completion:)dismiss(animated:completion:)的完成回调没有任何参数来指示转换是完成还是取消。如果在完成转换或取消转换时调用transitionContext.completeTransition(_:)方法,它们都将被调用。这种行为是故意设计的。