ios - UIView.animateWithDuration 的交互式过渡完成块从未在 animateTransition 内部调用
Posted
技术标签:
【中文标题】ios - UIView.animateWithDuration 的交互式过渡完成块从未在 animateTransition 内部调用【英文标题】:ios - interactive transition completion block for UIView.animateWithDuration never called inside animateTransition 【发布时间】:2016-07-03 22:36:42 【问题描述】:我使用带有平移手势识别器的自定义交互式弹出过渡。我有 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 中的完成块有时没有被调用。为什么会发生这种情况以及如何解决?
【问题讨论】:
【参考方案1】:当animateTransition(transitionContext:)
被调用并且用户交互不是交互的(如程序化动画触发器)时,系统似乎存在时间问题并且UIView.animateWithDuration
的completion
没有被调用,就像你一样描述。
我在工作中遇到了这种情况,我能够通过在调用 UIView.animateWithDuration(...)
之前从 animateTransition(transitionContext:)
内显式调用 UIPercentDrivenInteractiveTransition
对象上的 finishInteractiveTransition
来解决此问题。
对于我的情况,这是一个简单的解决方案,因为我的 UIViewControllerAnimatedTransitioning
对象有一个 UIPercentDrivenInteractiveTransition
子类的实例,并且我公开了一个 interactionInProgress
属性来确定我应该何时显式调用 finishInteractiveTransition
。
如果您在交互式转换对象上显式调用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(...)
另一种解决方案是将UIView.animateWithDuration
放在一个调度异步块中,并有一小段延迟。
【讨论】:
以上是关于ios - UIView.animateWithDuration 的交互式过渡完成块从未在 animateTransition 内部调用的主要内容,如果未能解决你的问题,请参考以下文章