[英]ios - interactive transition completion block for UIView.animateWithDuration never called inside animateTransition
I use custom interactive pop transition with pan gesture recognizer.我使用带有平移手势识别器的自定义交互式流行过渡。 I have subclass from UIPercentDrivenInteractiveTransition for handle user actions:
我有 UIPercentDrivenInteractiveTransition 的子类来处理用户操作:
class InteractiveTransitionManager: UIPercentDrivenInteractiveTransition {
var viewController: UIViewController?
var interactive: Bool = false
var popInProgress = false
var startX: CGFloat = 0
init(viewController: UIViewController) {
super.init()
self.viewController = viewController
self.viewController?.view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: "handlePan:"))
}
func handlePan(pan: UIPanGestureRecognizer) {
if pan.velocityInView(pan.view!.superview!).x > 0 && !popInProgress {
popInProgress = true
interactive = true
startX = pan.locationInView(pan.view!.superview!).x
viewController?.navigationController?.popViewControllerAnimated(true)
return
}
let curX = pan.locationInView(pan.view!.superview!).x
let progress: CGFloat = max(0, curX - startX) / pan.view!.frame.width
if pan.state == .Changed {
updateInteractiveTransition(progress)
} else if pan.state == .Ended || pan.state == .Cancelled {
if progress > 0.5 {
finishInteractiveTransition()
} else {
cancelInteractiveTransition()
}
popInProgress = false
interactive = false
}
}
}
And I have InteractivePopTransition class for animation of transition:我有用于过渡动画的 InteractivePopTransition 类:
class InteractivePopTransition: NSObject, UIViewControllerAnimatedTransitioning {
func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval {
return 0.3
}
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
let fromVC = transitionContext.viewControllerForKey(UITransitionContextFromViewControllerKey)!
let toVC = transitionContext.viewControllerForKey(UITransitionContextToViewControllerKey)!
let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)!
let toView = transitionContext.viewForKey(UITransitionContextToViewKey)!
let containterView = transitionContext.containerView()
let targetFrame = transitionContext.finalFrameForViewController(toVC)
toView.frame = CGRect(x: -targetFrame.size.width, y: targetFrame.origin.y, width: targetFrame.width, height: targetFrame.height)
containterView?.insertSubview(toView, belowSubview: fromView)
UIView.animateWithDuration(transitionDuration(transitionContext), animations: {
toView.frame = targetFrame
fromView.frame.origin.x = CGRectGetMaxX(targetFrame)
}, completion: { b in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled())
})
}
}
I have a problem that completion block in UIView.animateWithDuration sometime not called.我有一个问题,有时未调用 UIView.animateWithDuration 中的完成块。 Why this happens and how to fix it?
为什么会发生这种情况以及如何解决?
When animateTransition(transitionContext:)
is called and the user-interaction was not interactive (like a programmatic animation trigger), there seems to be a timing issue with the system and UIView.animateWithDuration
's completion
is not called, like you described.当
animateTransition(transitionContext:)
被调用并且用户交互不是交互式的(如程序化动画触发器)时,系统似乎存在计时问题并且UIView.animateWithDuration
的completion
没有被调用,就像你描述的那样。
I experienced this in my work and I was able to solve the issue by explicitly calling finishInteractiveTransition
on the UIPercentDrivenInteractiveTransition
object from within animateTransition(transitionContext:)
, before calling UIView.animateWithDuration(...)
.我在我的工作经历这个,我能够通过显式调用来解决问题
finishInteractiveTransition
上UIPercentDrivenInteractiveTransition
从内部对象animateTransition(transitionContext:)
,调用之前UIView.animateWithDuration(...)
This was a simple solution for my case because my UIViewControllerAnimatedTransitioning
object had an instance of the UIPercentDrivenInteractiveTransition
subclass, and I exposed an interactionInProgress
property to determine when I should explicitly call finishInteractiveTransition
.对于我的情况,这是一个简单的解决方案,因为我的
UIViewControllerAnimatedTransitioning
对象有一个UIPercentDrivenInteractiveTransition
子类的实例,并且我公开了一个interactionInProgress
属性来确定何时应该显式调用finishInteractiveTransition
。
If you explicitly call finishInteractiveTransition
on the interactive transition object then the completion block will be called.如果您在交互式过渡对象上显式调用
finishInteractiveTransition
,则将调用完成块。
class InteractivePopTransition: NSObject, UIViewControllerAnimatedTransitioning {
private var interactiveTransitionManager: InteractiveTransitionManager
...
func animateTransition(transitionContext: UIViewControllerContextTransitioning) {
...
if !interactiveTransitionManager.isInProgress {
// Weird state where system is telling you to animate a transition, but there
// is no interactive transition occurring. Manually finish the non-existant
// interactive transition so system will call other animation callbacks
// appropriately to complete the entire transition
interactiveTransitionManager.finish()
}
UIView.animateWithDuration(...)
}
}
Another solution is to put UIView.animateWithDuration
inside a dispatch async block with a small delay.另一个解决方案是将
UIView.animateWithDuration
放在一个有小延迟的调度异步块中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.