一个故事板的"容器视图"只是一个标准的UIView
对象。 没有特殊的"容器视图"类型。 实际上,如果您查看视图层次结构,您会发现 "容器视图" 是一个标准的UIView
:
![container view](https://istack.dev59.com/Sejof.webp)
要在程序中实现这一点,您需要使用"视图控制器包含":
- 通过在故事板对象上调用
instantiateViewController(withIdentifier:)
来实例化子视图控制器。
- 在父视图控制器中调用
addChild
。
- 使用
addSubview
将视图控制器的 view
添加到视图层次结构中(并根据需要设置frame
或约束)。
- 在子视图控制器上调用
didMove(toParent:)
方法,并传递对父视图控制器的引用。
请参阅 视图控制器编程指南中的"实现容器视图控制器" 部分以及 UIViewController 类参考中的 "实现容器视图控制器" 部分。
例如,在 Swift 4.2 中,代码可能如下所示:
override func viewDidLoad() {
super.viewDidLoad()
let controller = storyboard!.instantiateViewController(withIdentifier: "Second")
addChild(controller)
controller.view.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(controller.view)
NSLayoutConstraint.activate([
controller.view.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10),
controller.view.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10),
controller.view.topAnchor.constraint(equalTo: view.topAnchor, constant: 10),
controller.view.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10)
])
controller.didMove(toParent: self)
}
请注意,以上实际上并没有向层次结构中添加一个“容器视图”。如果您想这样做,可以执行以下操作:
override func viewDidLoad() {
super.viewDidLoad()
let containerView = UIView()
containerView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(containerView)
NSLayoutConstraint.activate([
containerView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10),
containerView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10),
containerView.topAnchor.constraint(equalTo: view.topAnchor, constant: 10),
containerView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10),
])
let controller = storyboard!.instantiateViewController(withIdentifier: "Second")
addChild(controller)
controller.view.translatesAutoresizingMaskIntoConstraints = false
containerView.addSubview(controller.view)
NSLayoutConstraint.activate([
controller.view.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
controller.view.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
controller.view.topAnchor.constraint(equalTo: containerView.topAnchor),
controller.view.bottomAnchor.constraint(equalTo: containerView.bottomAnchor)
])
controller.didMove(toParent: self)
}
如果要在不同的子视图控制器之间进行转换,并且您只想确保一个子视图的位置与上一个子视图的视图相同(即所有唯一放置约束都由容器视图指定,而无需每次重新构建这些约束),那么后一种模式非常有用。但是,如果只执行简单的视图包容性,则对于这个单独的容器视图的需求就不那么强烈。
在上面的示例中,我将translatesAutosizingMaskIntoConstraints
设置为false
并自己定义了约束条件。当然,您也可以将translatesAutosizingMaskIntoConstraints
保留为true
并为添加的视图同时设置frame
和autosizingMask
,如果您愿意。
请查看此答案的先前版本,了解 Swift 3 和 Swift 2 版本。
viewWillAppear
和viewWillDisappear
将会在子视图控制器上被正确调用。如果你有一个例子它们没有被调用,你应该澄清一下,或者发布自己的问题询问为什么它们没有被调用。 - Rob