一些观察:
- 实例化第二个视图控制器时,您正在调用
ViewControllerB()
。如果该视图控制器以编程方式创建其视图(这是不寻常的),那就很好了。但是,IBOutlet建议的存在暗示了第二个视图控制器的场景是在Interface Builder1z
中定义的,但是通过调用ViewControllerB()
,您并没有给情节提要板实例化该场景并连接所有出口的机会。因此,隐式解包的UILabel是nil,导致出现错误消息。
相反,您想在Interface Builder
中为目标视图控制器提供一个“ storyboard id” ,然后可以使用instantiateViewController(withIdentifier:
)它实例化(并连接
所有IB插座)。在Swift 3中let controller = storyboard!.instantiateViewController(withIdentifier: "scene storyboard id")
You can now access this
controller‘s
view.
- But if you really want to do
addSubview
(i.e. you’re not transitioning to the next scene), then you are engaging in a practice called “view controller containment”. You do not just want to simplyaddSubview
. You want to do some additional container view controller calls, e.g.:let controller = storyboard!.instantiateViewController(withIdentifier: "scene storyboard id")
addChild(controller)
controller.view.frame = … // or, better, turn offtranslatesAutoresizingMaskIntoConstraints
and then define constraints for this subview
view.addSubview(controller.view)
controller.didMove(toParent: self)
For more information about why this
addChild
(previously called
addChildViewController) and
didMove(toParent:)
(previously called
didMove(toParentViewController:)) are necessary, see
WWDC 2011 video #102 - Implementing UIViewController
Containment. In short,
you need to ensure that your view controller hierarchy stays in sync with your
view hierarchy, and these calls to
addChildand
didMove(toParent:)ensure
this is the case.
另请参阅 《View Controller编程指南》中的“ 创建自定义容器View
Controller ”。
顺便说一句,以上说明了如何以编程方式执行此操作。它
实际上是容易得多,如果您使用界面生成器“容器视图”。
在此处输入图片说明
这样,您就不必担心与这些与收容相关的任何呼叫,
Interface Builder会为您解决。
For Swift 2 implementation, see previous revision of this
answer.



