我使用自定义交互式弹出过渡和平移手势识别器。我有来自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
}
}
}
我有用于过渡动画的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())
})
}
}
我有一个问题,即有时未调用UIView.animateWithDuration中的完成块。为什么会发生这种情况以及如何解决?
答案 0 :(得分:1)
当调用animateTransition(transitionContext:)
且用户交互不是交互式的(例如程序动画触发器)时,系统和UIView.animateWithDuration
的{{1}}似乎存在计时问题不会像您描述的那样被调用。
我在工作中体会到了这一点,并且能够通过在调用completion
之前从finishInteractiveTransition
内部对UIPercentDrivenInteractiveTransition
对象上调用animateTransition(transitionContext:)
来解决此问题。 / p>
对于我的情况,这是一个简单的解决方案,因为我的UIView.animateWithDuration(...)
对象具有UIViewControllerAnimatedTransitioning
子类的实例,并且我公开了UIPercentDrivenInteractiveTransition
属性来确定何时应显式调用{{ 1}}。
如果您在交互式转换对象上显式调用interactionInProgress
,则将调用完成块。
finishInteractiveTransition
另一种解决方案是将finishInteractiveTransition
放在具有较小延迟的调度异步块中。