UIPercentDrivenInteractiveTransition无法在快速手势上完成动画 [英] UIPercentDrivenInteractiveTransition doesn't get to animation's completion on fast gesture

查看:1086
本文介绍了UIPercentDrivenInteractiveTransition无法在快速手势上完成动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个互动过渡。我的 func animateTransition(transitionContext:UIViewControllerContextTransitioning)很正常,我得到容器 UIView ,我加了两个 UIViewControllers 然后我在 UIView.animateWithDuration(持续时间,动画,完成)中进行动画更改。

I have created an interactive transition. My func animateTransition(transitionContext: UIViewControllerContextTransitioning) is quite normal, I get the container UIView, I add the two UIViewControllers and then I do the animation changes in a UIView.animateWithDuration(duration, animations, completion).

我在 UIViewController 中添加 UIScreenEdgePanGestureRecognizer 。它运作良好,除非我做一个非常快速的平底锅。

I add a UIScreenEdgePanGestureRecognizer to my from UIViewController. It works well except when I do a very quick pan.

在最后一个场景中,应用程序没有响应,仍然在同一个 UIViewController (转换似乎没有已经工作了)但后台任务运行。当我运行调试视图层次结构时,我看到新的 UIViewController 而不是前一个和前一个(至少它的 UIView )代表它应该在转换结束时站立的位置。

In that last scenario, the app is not responsive, still on the same UIViewController (the transition seems not to have worked) but the background tasks run. When I run the Debug View Hierarchy, I see the new UIViewController instead of the previous one, and the previous one (at least its UIView) stands where it is supposed to stand at the end of the transition.

我做了一些打印出来并检查点,我可以说,当问题发生时,动画完成(我的 animateTransition 方法中的那个)未到达,因此我无法调用 transitionContext.completeTransition 方法来完成或不完成转换。

I did some print out and check points and from that I can say that when the problem occurs, the animation's completion (the one in my animateTransition method) is not reached, so I cannot call the transitionContext.completeTransition method to complete or not the transition.

我也可以看到平底锅有时从 UIGestureRecognizerState.Began 直接到 UIGestureRecognizerState.Ended 而不去通过 UIGestureRecognizerState.Changed

I could see as well that the pan goes sometimes from UIGestureRecognizerState.Began straight to UIGestureRecognizerState.Ended without going through UIGestureRecognizerState.Changed.

当它通过 UIGestureRecognizerState.Changed 翻译 每个 UIGestureRecognizerState.Changed 州的 velocity 保持不变。

When it goes through UIGestureRecognizerState.Changed, both the translation and the velocity stay the same for every UIGestureRecognizerState.Changed states.

编辑:

以下是代码:

animateTransition 方法

func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
    self.transitionContext = transitionContext

    let containerView = transitionContext.containerView()
    let screens: (from: UIViewController, to: UIViewController) = (transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!, transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!)

    let parentViewController = presenting ? screens.from : screens.to
    let childViewController = presenting ? screens.to : screens.from

    let parentView = parentViewController.view
    let childView = childViewController.view

    // positionning the "to" viewController's view for the animation
    if presenting {
        offStageChildViewController(childView)
    }

    containerView.addSubview(parentView)    
    containerView.addSubview(childView)

    let duration = transitionDuration(transitionContext)

    UIView.animateWithDuration(duration, animations: {

        if self.presenting {
            self.onStageViewController(childView)
            self.offStageParentViewController(parentView)
        } else {
            self.onStageViewController(parentView)
            self.offStageChildViewController(childView)
        }}, completion: { finished in
            if transitionContext.transitionWasCancelled() {
                transitionContext.completeTransition(false)
            } else {
                transitionContext.completeTransition(true)
            }
    })
}

手势和手势处理程序:

weak var fromViewController: UIViewController! {
    didSet {
        let screenEdgePanRecognizer = UIScreenEdgePanGestureRecognizer(target: self, action: "presentingViewController:")
        screenEdgePanRecognizer.edges = edge
        fromViewController.view.addGestureRecognizer(screenEdgePanRecognizer)
    }
}

func presentingViewController(pan: UIPanGestureRecognizer) {
    let percentage = getPercentage(pan)

    switch pan.state {

    case UIGestureRecognizerState.Began:
        interactive = true
        presentViewController(pan)

    case UIGestureRecognizerState.Changed:
        updateInteractiveTransition(percentage)

    case UIGestureRecognizerState.Ended:
        interactive = false

        if finishPresenting(pan, percentage: percentage) {
            finishInteractiveTransition()
        } else {
            cancelInteractiveTransition()
        }

    default:
        break
    }
}

知道会发生什么吗?

编辑2:

以下是未公开的方法:

override func getPercentage(pan: UIPanGestureRecognizer) -> CGFloat {
    let translation = pan.translationInView(pan.view!)
    return abs(translation.x / pan.view!.bounds.width)
}

override func onStageViewController(view: UIView) {
    view.transform = CGAffineTransformIdentity
}

override func offStageParentViewController(view: UIView) {
    view.transform = CGAffineTransformMakeTranslation(-view.bounds.width / 2, 0)
}

override func offStageChildViewController(view: UIView) {
    view.transform = CGAffineTransformMakeTranslation(view.bounds.width, 0)
}

override func presentViewController(pan: UIPanGestureRecognizer) {
    let location = pan.locationInView((fromViewController as! MainViewController).tableView)
    let indexPath = (fromViewController as! MainViewController).tableView.indexPathForRowAtPoint(location)

    if indexPath == nil {
        pan.state = .Failed
        return
    }
    fromViewController.performSegueWithIdentifier("chartSegue", sender: pan)
}




  • 我删除了over添加行=>没有修复它

  • 我在中添加了 updateInteractiveTransition .Began ,在 .Ended 中,两者都=>没有修复它

  • 我开启了shouldRasterize我的 toViewController 的视图层,并让它一直开启=>没有修复它

    • I remove the "over" adding lines => didn't fix it
    • I added updateInteractiveTransition in .Began, in .Ended, in both => didn't fix it
    • I turned on shouldRasterize on the layer of the view of my toViewController and let it on all the time => didn't fix it

    • 但问题是为什么在做快速交互式手势时,它没有足够快地响应

      But the question is why, when doing a fast interactive gesture, is it not responding quickly enough

      只要我的手指足够长,它实际上适用于快速交互式手势。例如,如果我在超过(比方说)1cm时非常快速地平移,那就没关系。如果我在一个小表面上快速平移(再说一次)不到1厘米就不行了。

      It actually works with a fast interactive gesture as long as I leave my finger long enough. For example, if I pan very fast on more than (let say) 1cm, it's ok. It's not ok if I pan very fast on a small surface (let say again) less than 1cm


      可能的候选人包括动画的视图是太复杂了(或者像阴影一样有复杂的效果)

      Possible candidates include the views being animated are too complicated (or have complicated effects like shading)

      我也考虑过一个复杂的视图,但我不认为我的观点是真的很复杂。有一堆按钮和标签,一个自定义 UIControl 充当分段,一个图表(一旦控制器出现就加载),并在viewController中加载一个xib 。

      I thought about a complicated view as well but I don't think my view is really complicated. There are a bunch of buttons and labels, a custom UIControl acting as a segmented segment, a chart (that is loaded once the controller appeared) and a xib is loaded inside the viewController.

      好的我刚刚创建了一个项目,使用MINIMUM类和对象来触发问题。因此,要触发它,您只需从右向左快速轻扫即可。

      Ok I just created a project with the MINIMUM classes and objects in order to trigger the problem. So to trigger it, you just do a fast and brief swipe from the right to the left.

      我注意到它第一次非常容易,但是如果你第一次正常拖动视图控制器,那么触发它会更加困难(甚至不可能) ?)。在我的完整项目中,它并不重要。

      What I noticed is that it works pretty easily the first time but if you drag the view controller normally the first time, then it get much harder to trigger it (even impossible?). While in my full project, it doesn't really matter.

      推荐答案

      当我诊断出这个问题时,我发现手势是更改和结束状态事件发生在 animateTransition 之前甚至已经运行。所以动画在它开始之前就被取消/完成了!

      When I was diagnosing this problem, I noticed that the gesture's change and ended state events were taking place before animateTransition even ran. So the animation was canceled/finished before it even started!

      我尝试使用GCD动画同步队列来确保更新 UIPercentDrivenInterativeTransition 直到`animate:

      I tried using GCD animation synchronization queue to ensure that the updating of the UIPercentDrivenInterativeTransition doesn't happen until after `animate:

      private let animationSynchronizationQueue = dispatch_queue_create("com.domain.app.animationsynchronization", DISPATCH_QUEUE_SERIAL)
      

      然后我有一个实用工具方法来使用这个队列:

      I then had a utility method to use this queue:

      func dispatchToMainFromSynchronizationQueue(block: dispatch_block_t) {
          dispatch_async(animationSynchronizationQueue) {
              dispatch_sync(dispatch_get_main_queue(), block)
          }
      }
      

      然后我的手势处理程序确保更改并结束状态通过该队列路由:

      And then my gesture handler made sure that changes and ended states were routed through that queue:

      func handlePan(gesture: UIPanGestureRecognizer) {
          switch gesture.state {
      
          case .Began:
              dispatch_suspend(animationSynchronizationQueue)
              fromViewController.performSegueWithIdentifier("segueID", sender: gesture)
      
          case .Changed:
              dispatchToMainFromSynchronizationQueue() {
                  self.updateInteractiveTransition(percentage)
              }
      
          case .Ended:
              dispatchToMainFromSynchronizationQueue() {
                  if isOkToFinish {
                      self.finishInteractiveTransition()
                  } else {
                      self.cancelInteractiveTransition()
                  }
              }
      
          default:
              break
          }
      }
      

      所以,我有手势识别器的 .Began 状态暂停该队列,我让动画控制器在 animationTransition 中恢复该队列(确保队列在该方法运行之后再次启动,然后手势继续尝试更新 UIPercent DrivenInteractiveTransition object。

      So, I have the gesture recognizer's .Began state suspend that queue, and I have the animation controller resume that queue in animationTransition (ensuring that the queue starts again only after that method runs before the gesture proceeds to try to update the UIPercentDrivenInteractiveTransition object.

      这篇关于UIPercentDrivenInteractiveTransition无法在快速手势上完成动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆