В этом примере есть строка, которая говорит:
let vc = ViewControllerB()
Вы можете определить это представление контроллера представления в NIBи это будет работать нормально.Но если вы используете раскадровки, замените их на ...
let vc = storyboard!.instantiateViewController(withIdentifier: “identifier")
... где identifier
- это строка, которую вы указали в качестве «идентификатора раскадровки» в «Инспекторе удостоверений» в IBдля этой сцены.
Если это вызвано кнопкой или чем-то в этом роде, вы также можете удалить этот gotoVCB
в этом примере и просто выполнить модальное представление прямо в IBкак обычно (например, control - перетаскивание от кнопки к следующей сцене) и выбор «Представить модально».Но вам нужно убедиться, что вы настроили все init
методы, например:
class ViewControllerB: UIViewController {
// used if you use NIBs or just call `init()`
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
configure()
}
// used if you use storyboards
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
private func configure() {
modalPresentationStyle = .custom
transitioningDelegate = self
}
...
}
Не относясь к актуальному вопросу, я мог бы предложить разделить этого ответа код в отдельные объекты для предотвращения «раздувания» контроллера представления, с лучшим разделением обязанностей между переходящим объектом делегата, контроллером анимации и т. Д.
Например, возможно:
class ViewControllerB: UIViewController {
let customTransitioningDelegate = PopUpMenuTransitioningDelegate()
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
configure()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
func configure() {
modalPresentationStyle = .custom
transitioningDelegate = customTransitioningDelegate
}
}
И
class PopUpMenuTransitioningDelegate: NSObject, UIViewControllerTransitioningDelegate {
func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return PopUpMenuAnimationController(transitionType: .presenting)
}
func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
return PopUpMenuAnimationController(transitionType: .dismissing)
}
}
И
class PopUpMenuAnimationController: NSObject, UIViewControllerAnimatedTransitioning {
enum TransitionType {
case presenting
case dismissing
}
let transitionType: TransitionType
init(transitionType: TransitionType) {
self.transitionType = transitionType
super.init()
}
func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
return 1
}
func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
let containerView = transitionContext.containerView
guard let toVC = transitionContext.viewController(forKey: .to),
let fromVC = transitionContext.viewController(forKey: .from) else { return }
switch transitionType {
case .presenting:
containerView.addSubview(toVC.view)
var rect = fromVC.view.bounds
let menuHeight = fromVC.view.bounds.height / 2
rect.origin.y += fromVC.view.bounds.height
rect.size.height = menuHeight
toVC.view.frame = rect
toVC.view.alpha = 0
UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseOut], animations: {
rect.origin.y = menuHeight
toVC.view.frame = rect
toVC.view.alpha = 1
}, completion: { _ in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})
case .dismissing:
UIView.animate(withDuration: 0.4, delay: 0, options: [.curveEaseOut], animations: {
var rect = fromVC.view.frame
rect.origin.y = toVC.view.bounds.height
fromVC.view.frame = rect
fromVC.view.alpha = 0
}, completion: { _ in
transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
})
}
}
}
Это отделяет переходящий контроллер делегата и анимации от контроллера представления и позволяет использовать его с другими контроллерами представления, если вам когда-либо понадобится.
Обратите внимание, я тоже немного более осторожен с параметром completeTransition
.Как только вы начинаете играть с интерактивными переходами, вы можете поддерживать отменяемые переходы.