使用Swift-5.0.1,Xcode-10.2.1,iOS-12.2和
我发现一个非常奇怪的问题(已经占用了我太多的时间):
我的带有UINavigationController的导航堆栈运行良好。我可以从一个ViewController推送并弹出到下一个。以我为例,我将Coordinator模式与Router配合使用(但是我想这对这个问题并不重要)。
我在UINavigationController上使用两种方法在导航堆栈中向后弹出
popViewController
popToRootViewController
想法是使用popViewController
返回堆栈中的一个ViewController。并使用popToRootViewController
返回到堆栈中的第一个ViewController。到目前为止,一切都很好!
但是现在问题出在
如果我对popBack-navigation-transitions使用自定义动画过渡,事情就搞砸了!
更确切地说,使用popToRootViewController
进行自定义过渡的导航栏已完全混乱,无法正确制作动画!!!!
“不正确”的意思是:导航栏会立即弹出而不是动画。
使用popViewController
时,一切正常,导航栏按预期完成了平滑过渡。
为什么在导航栏动画方面popViewController
和popToRootViewController
之间的区别?
我知道我也可以使用Segue进行自定义动画。但是我不想使用Segue,因为它可以防止代码去耦,从而避免测试。我真的很想保留我的协调器和路由器,并使用UINavigationController-Delegate动画化过渡。
以下是展示区别的视频:
->屏幕内容无关紧要。观看标题以查看哪个页面-nr,并观察导航栏动画。
->请观察导航栏,并清楚注意从第3页到第2页的转换与从第3页到第1页的转换之间的区别。
->您可以清楚地注意到,从第3页到第1页的过渡的导航栏是瞬时的,而第1页的其余部分按预期淡入(因为它不应该-NavBar太快了) !!!)
->对于从第3页到第2页的过渡,所有内容都会进行动画处理,包括导航栏以及页面的所有其余部分(应该是!!)
这是我的代码:
popViewController调用:
let t = CustomFadeTransition(withDuration: 1.0)
self.router.popModule(transition: t, animated: true)
popToRootViewController调用:
let t = CustomFadeTransition(withDuration: 1.0)
self.router.popToRootModuleWithTransition(transition: t, animated: true)
具有过渡委托方法(证明)的路由器实现
final class Router: NSObject, RouterProtocol {
private weak var rootController: UINavigationController?
private var completions: [UIViewController : () -> Void]
private var transition: UIViewControllerAnimatedTransitioning?
// ...
func popModule(transition: UIViewControllerAnimatedTransitioning?, animated: Bool) {
self.transition = transition
let _ = rootController?.popViewController(animated: animated)
}
func popToRootModuleWithTransition(transition: UIViewControllerAnimatedTransitioning?, animated: Bool) {
self.transition = transition
let _ = self.rootController?.popToRootViewController(animated: animated)
}
}
extension Router: UINavigationControllerDelegate, UIViewControllerTransitioningDelegate {
func navigationController(_ navigationController: UINavigationController, animationControllerFor operation: UINavigationController.Operation, from fromVC: UIViewController, to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self.transition
}
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return self.transition
}
}
。
CustomFadeTransition实现(此处并不重要,因为任何Transition都显示了混乱的导航栏...但是要在此处完成代码。)
class CustomFadeTransition: NSObject, UIViewControllerAnimatedTransitioning {
let duration: TimeInterval
let presenting: Bool
init(withDuration: TimeInterval = 0.2, presenting: Bool = true) {
self.duration = withDuration
self.presenting = presenting
super.init()
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let from = transitionContext.viewController(forKey: .from)!
let to = transitionContext.viewController(forKey: .to)!
let container = transitionContext.containerView
if presenting {
container.addSubview(to.view)
to.view.alpha = 0.0
} else {
container.insertSubview(to.view, belowSubview: from.view)
}
UIView.animate(withDuration: (duration * 2), animations: {
if self.presenting {
to.view.alpha = 1.0
} else {
from.view.alpha = 0.0
}
}, completion: { value in
let success = !transitionContext.transitionWasCancelled
if !success {
to.view.removeFromSuperview()
}
transitionContext.completeTransition(success)
})
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return duration
}
}