Использование Swift-5.0.1, Xcode-10.2.1, iOS-12.2,
У меня наблюдается очень странная проблема (которая заняла слишком много времени):
Мой стек навигации с UINavigationController работает хорошо.Я могу нажать и выскочить из одного ViewController в другой.В моем случае я использую шаблон Координатора с Маршрутизатором (но это не важно для этой проблемы здесь, я предполагаю).
Я использую два метода на моем UINavigationController, чтобы выскочить назад в моем стеке навигации
popViewController
popToRootViewController
Идея состоит в том, чтобы использовать popViewController
для возврата одного ViewController в стек.И использовать popToRootViewController
, чтобы вернуться обратно к первому ViewController в стеке.Пока все хорошо!
Но теперь проблема:
Если я использую собственные переходы анимации для переходов popBack-navigation, все будет запутано!
Точнее, панель навигации, использующая popToRootViewController
с пользовательским переходом, полностью испорчена и не выполняет анимацию должным образом !!!!
С "не правильно" я имею в виду:Панель навигации выскакивает мгновенно, а не анимируется.
При использовании popViewController
все работает, и панель навигации делает переход плавным и приятным, как и ожидалось.
Почему разница между popViewController
и popToRootViewController
с точки зрения анимации навигационной панели ???
Я знаю, что мог бы также использовать Segue для пользовательских анимаций.Но я не хочу использовать Segue, поскольку он предотвращает расцепление кода и, следовательно, тестирование.Я действительно хотел бы сохранить свой координатор и маршрутизатор и анимировать переходы с помощью UINavigationController-Delegate.
Вот видео, которое показывает разницу:
-> содержимое экрановне имеет значения.Просматривайте заголовки, чтобы увидеть, какой номер страницы и наблюдайте анимацию панели навигации.
-> пожалуйста, обратите внимание на панель навигации и обратите внимание на разницу между переходом со страницы 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)
Реализация Router с методами делегата перехода (выдержки ..)
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 (здесь не важно, так как любой переход показывает запутанныйвверх Navigation-Bar ... но чтобы быть полным здесь код ..)
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
}
}