一尘不染

在另一个视图控制器中将视图控制器添加为子视图

swift

我没有找到有关此问题的文章,但没有一个解决我的问题。

就像我说的那样。

  1. ViewControllerA
  2. ViewControllerB

我试图将ViewControllerB添加为ViewControllerA的子视图,但是它
抛出类似“ fatal error: unexpectedly found nil while unwrapping an Optional value” 的错误。

下面是代码…

ViewControllerA

var testVC: ViewControllerB = ViewControllerB();

override func viewDidLoad()
{
    super.viewDidLoad()
    self.testVC.view.frame = CGRectMake(0, 0, 350, 450);
    self.view.addSubview(testVC.view);
    // Do any additional setup after loading the view.
}

ViewControllerB只是一个带有标签的简单屏幕。

ViewControllerB

 @IBOutlet weak var test: UILabel!

override func viewDidLoad() {
    super.viewDidLoad()
    test.text = "Success" // Throws ERROR here "fatal error: unexpectedly found nil while unwrapping an Optional value"
}

EDIT

根据用户答案的​​建议解决方案,ViewControllerA中的ViewControllerB不在屏幕上。灰色边框是我


阅读 263

收藏
2020-07-07

共1个答案

一尘不染

一些观察:

  1. 实例化第二个视图控制器时,您正在调用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.

  1. 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 simply addSubview. 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 off translatesAutoresizingMaskIntoConstraints 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 addChild and didMove(toParent:) ensure
this is the case.

另请参阅 《View Controller编程指南》中的“ 创建自定义容器View
Controller ”。

顺便说一句,以上说明了如何以编程方式执行此操作。它
实际上是容易得多,如果您使用界面生成器“容器视图”。

在此处输入图片说明

这样,您就不必担心与这些与收容相关的任何呼叫,
Interface Builder会为您解决。

For Swift 2 implementation, see previous revision of this
answer
.

2020-07-07