web-dev-qa-db-fra.com

ContainerView avec plusieurs séquences intégrées

Existe-t-il un moyen d'avoir un seul ContainerView avec plusieurs séquences d'intégration? L'objectif est qu'un ContainerView contienne quelques ViewControllers différents selon les boutons sur lesquels vous avez appuyé; un seul va être visible à la fois. Je souhaite utiliser des séquences intégrées afin que dans Interface Builder les storyboards soient automatiquement affichés à la même taille que ContainerView.

Je me rends compte que je peux redimensionner manuellement les autres ViewControllers dans InterfaceBuilder, mais je veux le dimensionnement automatique fourni par la séquence d'intégration. Si une autre façon de le faire est disponible, ce serait bien aussi. Ne pas charger les vues sur viewDidLoad est très bien - comme mentionné précédemment, le ViewController montré peut changer en fonction des boutons enfoncés.

43
Steve Haley

Non, il n'y a aucun moyen d'avoir plusieurs séquences d'intégration dans une vue de conteneur. Une façon de faire toute la configuration dans IB, serait de faire du contrôleur intégré un UITabBarController (avec la barre d'onglets cachée). Vous pouvez alors avoir autant de contrôleurs dans les onglets que vous le souhaitez et basculer vers eux dans le code à l'aide de la propriété selectedIndex de UITabBarController.

44
rdelmar

J'ai trouvé ce merveilleux article qui explique exactement comment le faire: http://sandmoose.com/post/35714028270/storyboards-with-custom-container-view-controllers

vous obtenez votre conteneur et pouvez appeler n'importe quel contrôleur de vue derrière, il y a un peu de configuration pour que tout soit lié mais une fois terminé, vous obtenez un storyboard toujours utilisable.

15
Kanjiroushi

Je reconnais que cette question est un peu ancienne, mais je voulais y répondre au cas où vous chercheriez toujours ou si d'autres personnes trouvaient cela. J'avais un problème similaire et j'y ai travaillé.

En bref, vous aurez trois couches:
- un contrôleur de vue externe ("ExternalViewController")
- un gestionnaire de contrôleur de vue ("ViewControllerManager")
- les contrôleurs de vue enfant entre lesquels vous voulez réellement basculer ("ChildViewController")

Utilisez une vue de conteneur dans ExternalViewController avec une séquence d'intégration au ViewControllerManager. ViewControllerManager lui-même contiendrait alors d'autres ChildViewControllers par programme comme décrit dans ce Apple , en particulier la section sur l'ajout et la suppression d'un enfant.

Lorsque vous ajoutez un contrôleur de vue enfant, définissez son cadre pour qu'il soit identique à celui du ViewControllerManager (puisque vous effectuez cette opération dans ViewControllerManager, définissez le cadre de l'enfant égal à self.view.frame). Vous aurez également besoin d'un peu de logique et d'un contrôle externe pour effectuer la commutation à l'intérieur de ExternalViewController, bien sûr.

J'espère que cela t'aides!

14
UberJason

Oui, j'ai pu réaliser ce que vous cherchez en vous inspirant de @rdelmar post. Ce que vous devez faire est d'incorporer un UITabBarViewController dans votre vue conteneur. Ensuite, vous choisissez par programme le contrôleur que vous souhaitez présenter. Vous pouvez également souhaiter masquer la barre d'onglets.

Container view indirectly containing more views

Si vous le souhaitez, vous pouvez également masquer les barres d'onglets visibles dans le fichier storyboard

Vous pouvez choisir le contrôleur de vue que vous souhaitez présenter en sous-classant l'UITabBarController:

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

Vous pouvez masquer la barre d'onglets dans votre contrôleur de vue en appelant self.tabBarController?.tabBar.hidden = truedans viewDidLoad ().

14
Andrej

J'ai aussi lutté longtemps avec ça. J'ai eu le cas où j'avais différents contrôleurs de vue de table intégrés, mais similaires, que je voulais montrer en fonction d'un paramètre défini dans la transition vers le contrôleur de vue. Ce qui a fonctionné était de mettre dans le conteneur intégré avec un IBOutlet dans le contrôleur de vue. Le conteneur peut avoir des contraintes de taille définies dans IB. Cependant, ne faites aucune séquence d'intégration dans IB. Ensuite, dans viewDidLoad, j'ajoute par programme le contrôleur de vue correct et j'épingle ses bords au conteneur d'intégration.

Le cœur de cette approche se retrouve dans le code suivant (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)
            }
        }
    }
}

Dans ColorVC, on voit le conteneur IBOutlet et le paramètre "color" défini par le contrôleur de vue de table principal. Les RedTableVC, GreenTableVC et BlueTableVC sont tous sous-classés de ColorTableVC qui est sous-classé de UITableViewController. L'héritage commun me permet d'utiliser une variable "colorTableVC" pour pointer vers l'un des contrôleurs instanciés. (Pas entièrement nécessaire). Mais cela évite de dupliquer le code ci-dessous pour ajouter la vue dans la hiérarchie et épingler le nouveau contrôleur à la vue du conteneur. En haut, j'ai fait une extension sur UIView pour épingler une vue aux bords de ses parents.

L'image suivante montre comment le projet et en particulier le contrôleur de vue à droite a été configuré dans IB. Pour cet exemple, j'ai fait la hauteur du contrôleur "intégré" la moitié de la hauteur du contrôleur de vue principal - donc lorsque vous faites pivoter l'appareil, on peut voir que les contraintes définies dans IB sont effectivement appliquées.

Embedded controller IB setup

2
anorskdev

J'y suis parvenu en utilisant -shouldPerformSegueWithIdentifier:sender:. J'ai un conteneur qui est passé un objet et selon le type de cet objet décide quel contrôleur de vue enfant à afficher.

La structure semble un peu trop compliquée mais permet au contrôleur de vue de base d'ignorer les différents types de tâches que j'ai, laissant cela au contrôleur de vue de conteneur. Le contrôleur de vue de conteneur a alors plusieurs vues de conteneur dont les séquences ne sont effectuées qu'en fonction du type de tâche.

Je ne sais pas si vous pouvez réellement effectuer les séquences d'intégration manuellement en appelant -performSegueWithIdentifier:sender: mais cela pourrait aussi être une possibilité.

2
Fábio Oliveira