В настоящее время принятый ответ (на момент написания этого ответа) не идеален, поскольку он может неправильно позиционировать элементы пользовательского интерфейса, такие как панель навигации, во время анимации или приводить к другим сбоям макета , как описано в ответ Марко Николовски .Однако нажатие снимка текущего представления контроллера представления поверх представления следующего контроллера представления для целей анимации также не является идеальным, поскольку его нельзя использовать для контроллеров представления, в которых во время анимации происходит какой-либо вид.переход к следующему контроллеру представления в качестве снимка - это просто статическое изображение .
Принимая базовую идею cclogg вот моя реализация плавного перехода между двумя контроллерами представления, который не заботится о значениях альфа:
/// Replaces the window's current `rootViewController` with the `newViewController`
/// passed as a parameter. If `animated`, the window animates the replacement
/// with a cross dissolve transition.
///
/// - Parameters:
/// - newViewController: The view controller that replaces the current view controller.
/// - animated: Specifies if the transition between the two view controllers is animated.
/// - duration: The transition's duration. (Ignored if `animated == false`)
private func swapCurrentViewController(with newViewController: UIViewController,
animated: Bool = true,
duration: TimeInterval = 1) {
// Get a reference to the window's current `rootViewController` (the "old" one)
let oldViewController = window?.rootViewController
// Replace the window's `rootViewController` with the new one
window?.rootViewController = newViewController
if animated, let oldView = oldViewController?.view {
// Add the old view controller's view on top of the new `rootViewController`
newViewController.view.addSubview(oldView)
// Remove the old view controller's view in an animated fashion
UIView.transition(with: window!,
duration: duration,
options: .transitionCrossDissolve,
animations: { oldView.removeFromSuperview() },
completion: nil)
}
}
Важно заменитьrootViewController
окна до инициации перехода или анимации, потому что именно так новый контроллер представления узнает свой контекст, то есть правильные поля макета и т. д.
? Это способчтобы пойти, если вам действительно нужно заменить rootViewController
окна по любой причине.Тем не менее, я хочу отметить, что с архитектурной точки зрения, на мой взгляд, гораздо лучшим подходом является создание контроллера представления, который будет единолично отвечать за обработку переходов между двумя другими контроллерами представления, и установить его как rootViewController
окна итогда никогда не меняй его .Это хорошо объяснено в этом ответе на аналогичный вопрос.