1. ホーム
  2. ios

[解決済み] ビューコントローラを別のビューコントローラのサブビューとして追加する

2023-05-22 21:38:13

質問

この問題に対するいくつかの投稿を見つけましたが、どれも私の問題を解決してくれませんでした。

私がしたように言う...

  1. ビューコントローラA
  2. ビューコントローラB

ViewControllerAにViewControllerBをサブビューとして追加しようとしましたが、"のようなエラーを投げています。 fatal error: unexpectedly found nil while unwrapping an Optional value というエラーが発生します。

以下はそのコードです...

ビューコントローラA

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が画面外に出てしまうのですが、どうしたらいいでしょうか?グレーの枠はサブビューに作った枠です。

どのように解決するのですか?

いくつかの意見を述べます。

  1. 2つ目のビューコントローラをインスタンス化するとき、あなたは ViewControllerB() . もしそのビューコントローラがプログラムでビューを作成するのであれば(これは珍しいことですが)、それは問題ないでしょう。しかし IBOutlet の存在は、この2番目のビューコントローラのシーンがInterface Builderで定義されたことを示唆しますが、その際に ViewControllerB() を呼び出すことによって、ストーリーボードにそのシーンをインスタンス化し、すべてのアウトレットをフックする機会を与えていないことになります。したがって、暗黙のうちにアンラップされた UILabelnil であり、エラーメッセージが表示されます。

    その代わりに、Interface Builderで目的地のビューコントローラに "ストーリーボードID" を与え、その上で instantiateViewController(withIdentifier:) を使ってインスタンス化します(そして、すべての IB アウトレットをフックします)。Swift 3では。

    let controller = storyboard!.instantiateViewController(withIdentifier: "scene storyboard id")
    
    

    これで、この controller 's view .

  2. しかし、本当にやりたいのであれば addSubview (を本当に行いたいのであれば(つまり、次のシーンに遷移しないのであれば)、あなたは "ビューコントローラーの格納と呼ばれる行為を行っていることになります。単純に addSubview . あなたは、例えば、いくつかの追加のコンテナビューコントローラの呼び出しを行いたいと思います。

    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)
    
    

    なぜこの addChild (以前は addChildViewController ) と didMove(toParent:) (以前は didMove(toParentViewController:) ) が必要な場合は WWDC 2011 ビデオ #102 - UIViewController のコンテインメントの実装 . 要するに、ビューコントローラの階層がビューの階層と同期していることを確認する必要があり、これらの呼び出しは addChilddidMove(toParent:) がそうであることを確認します。

    も参照してください。 カスタムコンテナビューコントローラの作成 を参照してください。 ビューコントローラ プログラミングガイド" を参照してください。


ところで、上記はプログラム的にこれを行う方法を示しています。実際はInterface Builderのquot;container view"を使うと、もっと簡単です。

そうすれば、これらのコンテント関連の呼び出しについて心配する必要はありませんし、Interface Builderが代わりに処理してくれるでしょう。

Swift 2 の実装については この回答の以前の改訂版 .