web-dev-qa-db-ja.com

複数のセグエが埋め込まれたContainerView

複数の埋め込みセグエを含む単一のContainerViewを使用する方法はありますか?目的は、押されたボタンに応じて、ContainerViewがいくつかの異なるViewControllerを保持することです。一度に1つだけ表示されます。 Interface BuilderでストーリーボードがContainerViewと同じサイズで自動的に表示されるように、埋め込みセグエを使用します。

InterfaceBuilderで他のViewControllerのサイズを手動で変更できることを認識していますが、埋め込みセグエによって提供される自動サイズ設定が必要です。それを行う別の方法が利用可能であれば、それも問題ないでしょう。 viewDidLoadでビューをロードしなくても構いません-前述のように、表示されているViewControllerは押されたボタンに応じて変化します。

43
Steve Haley

いいえ、1つのコンテナビューに複数のセグエを埋め込む方法はありません。 IBですべてのセットアップを行う1つの方法は、組み込みコントローラーをUITabBarControllerにすることです(タブバーは非表示になります)。その後、必要な数のタブにコントローラーを配置し、UITabBarControllerのselectedIndexプロパティを使用してコード内でコントローラーに切り替えることができます。

44
rdelmar

その方法を正確に説明したこの素晴らしい記事を見つけました: http://sandmoose.com/post/35714028270/storyboards-with-custom-container-view-controllers

コンテナを取得し、背後にある任意のView Controllerを呼び出すことができます。すべてをリンクするための設定が少しありますが、一度完了すると、まだ使用可能なストーリーボードが得られます。

15
Kanjiroushi

この質問は少し古いと思いますが、まだ見ている場合や他の人がこれを見つけた場合に答えたいと思います。同様の問題があり、それを回避しました。

つまり、次の3つのレイヤーがあります。
-外部View Controller( "ExternalViewController")
-ビューコントローラーマネージャー( "ViewControllerManager")
-実際に切り替えたい子View Controller( "ChildViewController")

ViewControllerManagerにセグエを埋め込み、ExternalViewControllerのコンテナビューを使用します。 ViewControllerManager自体は このAppleドキュメンテーション 、特に子の追加と削除に関するセクションで説明されているように、プログラムで他のChildViewControllersを保持します。

子View Controllerを追加するとき、そのフレームをViewControllerManagerのフレームと同じに設定します(これをViewControllerManager内で行うため、子のフレームをself.view.frameと等しく設定します)。もちろん、ExternalViewController内で切り替えを行うためのロジックと外部コントロールも必要です。

お役に立てれば!

14
UberJason

はい、@ rdelmarの投稿に触発されて、あなたが探しているものを達成することができました。必要なことは、UITabBarViewControllerをコンテナビューに埋め込むことです。次に、提示するコントローラーをプログラムで選択します。タブバーを非表示にすることもできます。

Container view indirectly containing more views

必要に応じて、ストーリーボードファイルに表示されるタブバーを非表示にすることもできます

UITabBarControllerをサブクラス化することにより、表示するView Controllerを選択できます。

override func viewDidLoad() {
    super.viewDidLoad()
    self.selectedIndex = 1
}

ViewDidLoad()でself.tabBarController?.tabBar.hidden = trueinを呼び出すことにより、View ControllerでTab Barを非表示にできます。

14
Andrej

私もこれに長い間苦労しました。 View Controllerのセグエに設定されたパラメータに応じて表示したい、異なるが同様の埋め込みTable View Controllerがあるケースがありました。うまくいったのは、View ControllerのIBOutletで埋め込みコンテナに入れることでした。コンテナには、IBでサイズ制限を設定できます。ただし、IBにセグエを埋め込まないでください。次に、viewDidLoadで、正しいView Controllerをプログラムで追加し、そのエッジを埋め込みコンテナーに固定します。

このアプローチの中心は、次のコード(Swift 4)にあります。

extension UIView {
    func pinToParent() {
        self.translatesAutoresizingMaskIntoConstraints = false
        let attributes: [NSLayoutAttribute] = [.top, .bottom, .right, .left]
        NSLayoutConstraint.activate(attributes.map {
            NSLayoutConstraint(item: self, attribute: $0, relatedBy: .equal, toItem: self.superview, attribute: $0, multiplier: 1, constant: 0)
        })
    }
}

class ColorVC: UIViewController {

    @IBOutlet weak var tableContainer: UIView!
    var color : rgb = .red

    fileprivate var colorTableVC : ColorTableVC?

    override func viewDidLoad() {
        super.viewDidLoad()

        switch color {
        case .red:
            colorTableVC = RedTableVC.init(style: .plain)
        case .green:
            colorTableVC = GreenTableVC.init(style: .plain)
        case .blue:
            colorTableVC = BlueTableVC.init(style: .plain)
        }
        if let vc = colorTableVC {
            if (vc.view) != nil {
                self.addChildViewController(vc)
                tableContainer.addSubview(vc.view)
                vc.view.pinToParent()
                vc.didMove(toParentViewController: self)
            }
        }
    }
}

ColorVCには、コンテナIBOutletとメインテーブルビューコントローラーによって設定された「color」パラメーターが表示されます。 RedTableVC、GreenTableVC、およびBlueTableVCはすべて、UITableViewControllerからサブクラス化されたColorTableVCからサブクラス化されています。共通の遺産により、1つの「colorTableVC」変数を使用して、インスタンス化されたコントローラーのいずれかを指すことができます。 (完全に必要というわけではありません)。ただし、これにより、以下のコードを重複して階層にビューを追加し、新しいコントローラーをコンテナービューに固定することは避けられます。上部では、ビューをその親の端に固定するために、UIViewで拡張を行いました。

次の画像は、プロジェクト、特に右側のView ControllerがIBでどのように設定されたかを示しています。この例では、「埋め込み」コントローラーの高さをメインビューコントローラーの高さの半分にしました。したがって、デバイスを回転させると、IBで設定された制約が実際に適用されていることがわかります。

Embedded controller IB setup

2
anorskdev

-shouldPerformSegueWithIdentifier:sender:を利用することでそれを達成しました。オブジェクトを渡すコンテナがあり、このオブジェクトのタイプに応じて、どの子View Controllerを表示するかを決定します。

構造はやや複雑すぎるように見えますが、ベースビューコントローラーは、私が持っているさまざまなタイプのタスクを無視し、それをコンテナービューコントローラーに任せることができます。コンテナビューコントローラには、タスクのタイプに応じてのみ実行されるセグエの複数のコンテナビューがあります。

-performSegueWithIdentifier:sender:を呼び出すことで実際に埋め込みセグエを手動で実行できるかどうかはわかりませんが、可能性もあります。

2
Fábio Oliveira