我在http://sandmoose.com/post/35714028270/storyboards-with-custom-container-view-controllers的帮助下找到了一种可能的解决方案
在入口点视图控制器中,放置一个具有自动布局约束的容器视图,将容器视图的顶部和底部与顶部和底部布局指南对齐。
然后,容器视图本身需要嵌入您选择的任何视图控制器。这样,目标视图控制器将始终存在于容器视图的范围内。容器视图也将受到初始视图控制器的顶部和底部布局指南的正确约束。
实现此目的的一种方法:实现一个将接收 segue 通知的协议 - 例如:
protocol SegueDelegate {
func willSegue(to: UIViewController)
func didSegue(to: UIViewController)
}
实现一个 UIViewController 的子类,它具有对 SegueDelegate 的引用,例如
class ContainedViewController: UIViewController {
weak var segueDelegate: SegueDelegate?
...
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
segueDelegate?.willSegue(to: segue.destination)
}
}
让您的初始消息视图控制器实现协议。
extension MSMessagesAppViewController: SegueDelegate {
func didSegue(to destination: UIViewController) {
guard let destination = destination as? ContainedViewController else {
return
}
// Reference through IBOutlet or something
containerViewController.embed(destination)
}
}
这里的 containerViewController 必须实现一个嵌入方法,将显示的视图控制器与新的交换,例如
class ContainerViewController: UIViewController {
...
func embed(_ viewController: UIViewController) {
let source = childViewControllers.first
if source == viewController {
return
}
source?.willMove(toParentViewController: nil)
addChildViewController(viewController)
if let source = source {
// Do transition here if you want
viewController.view.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height)
view.addSubview(viewController.view)
viewController.didMove(toParentViewController: self)
source.willMove(toParentViewController: nil)
source.removeFromParentViewController()
} else {
viewController.view.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height)
view.addSubview(viewController.view)
viewController.didMove(toParentViewController: self)
}
// Assigned in viewDidLoad of MSMessagesAppViewController or similar
segueDelegate?.didSegue(to: viewController)
}
}