Relier les contrôleurs de vue enfant à un contrôleur de vue parent dans storyboard

pouvez-vous associer des contrôleurs de vue enfant à un contrôleur de vue conteneur personnalisé dans Storyboard?

je peux relier des contrôleurs de vue enfant à un contrôleur de vue tab, et je peux relier un contrôleur de vue à un contrôleur de navigation.

Que dois-je faire au contenant VC pour accepter les CV d'enfants?

56
demandé sur AstroCB 2011-11-20 05:14:18

5 réponses

comme une sorte de combinaison des réponses de Caleb et Matt, j'ai fait:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"cpdc_check_embed"]) {
        self.checkVC = segue.destinationViewController;
    }
}

...où checkVC est une propriété du contrôleur des conteneurs:

@property (weak,nonatomic) PXPCheckViewController * checkVC;

il vous suffit de régler votre embed segue Storyboard ID à tout ce que vous voulez (dans ce cas, cpdc_check_embed ):

check embed screen in Xcode

...et puis vérifiez l'identifiant dans -prepareForSegue:sender: .

Toujours pas un exutoire, mais plus propre que celui de Matt (IMHO) et plus spécifique que celui de Caleb, et vous obtenez toujours un joli storyboard:

enter image description here

75
répondu Ben Mosher 2012-09-05 15:04:44

le storyboard traite très bien des contrôleurs de vue de conteneur intégrés, affichant des séquences vers les contrôleurs de vue enfant/racine de sorte que les relations sont clairement indiquées. Il est également agréable de voir comment les contrôleurs de vue des enfants et des parents sont séparés en différentes scènes.

Si vous voulez obtenir cet effet dans votre propre projet, alors il y a un truc qui n'est pas parfait, mais très simple. Dans mon exemple, supposons que j'ai un contrôleur de vue de conteneur qui agit comme une barre d'onglet contrôleur avec seulement deux onglets, 'gauche' et 'droite'. Je veux qu'une scène représente le contrôleur de vue parent, et deux scènes distinctes représentent à la fois le contrôleur de vue enfant "gauche" et le contrôleur de vue enfant "droit".

même si c'est impossible, ce serait bien si je pouvais créer IBOutlet s à partir du contrôleur de vue de conteneur à ses enfants dans différentes scènes, et puis quand mon contrôleur de vue de conteneur est affiché configurer le parent / enfant relations selon les règles décrites le UIViewController documentation . Si nous avions des références à nos contrôleurs de vue d'enfant "gauche" et "droite", alors nous pourrions mettre en place les relations sans problème.

la solution standard à ce problème de référencement est de créer des références aux contrôleurs de vue enfants en faisant glisser les sorties Object dans la scène du contrôleur de vue conteneur, puis en spécifiant leur type de classe comme étant des instances des classes de contrôleur de vue d'enfant.

afin de garder les enfants séparés dans différentes scènes comme les contenants encastrés D'Apple, cependant, nous allons utiliser un tour différent. Tout d'abord, supposons que nous ayons les propriétés suivantes déclarées dans notre classe de conteneurs, ContainerViewController :

@property (nonatomic, strong, readwrite) UIViewController *leftViewController;
@property (nonatomic, strong, readwrite) UIViewController *rightViewController;

dans notre storyboard, sélectionnez la scène représentant le contrôleur de vue "gauche". Dans les attributs inspector, définissez la propriété identifier du contrôleur de vue à "cvc_leftViewController" ("cvc_" se réfère à ContainerViewController , mais vraiment, l'identifiant peut être tout ce que vous voulez). Faites la même chose pour la scène du contrôleur de la vue de droite, paramétrant son identifiant à "cvc_rightViewController" .

insérer maintenant le code suivant dans ContainerViewController ' s viewDidLoad méthode:

if (self.storyboard) {
    _leftViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"cvc_leftViewController"];
    _rightViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"cvc_rightViewController"];
}

quand ContainerViewController est chargé à partir du storyboard, il va saisir les contrôleurs de vue "gauche" et "droite" de leurs scènes respectives et de mettre des références à eux par l'intermédiaire de ses propriétés. Maintenant que vous avez le contrôle des instances du contrôleur de la vue enfant, vous pouvez configurer les relations parent/enfant comme vous le souhaitez. Pour savoir comment faire cela correctement référez-vous à la UIViewController documentation .

ce tour n'est pas parfait, et a beaucoup de mises en garde, mais si vous êtes prudent, vous pouvez le faire fonctionner correctement pour votre projet.

Edit: bien que ce soit complètement inutile et ne si vous voulez dire quelque chose, si vous vraiment vraiment voulez avoir les connexions d'affichage de storyboard à partir de votre conteneur à vos contrôleurs de vue enfant tout comme les conteneurs intégrés D'Apple, il suffit d'utiliser ma méthode ci-dessus et puis configurer les segments directement entre la scène du conteneur aux scènes enfants, et tout simplement ne jamais effectuer ces segments. Maintenant tout va fonctionner correctement et être joli aussi.

15
répondu Matt 2012-07-03 18:19:01

pouvez-vous associer des contrôleurs de vue enfant à une vue de conteneur personnalisé contrôleur dans Storyboard?

je pense que ce que vous demandez ici est comment connecter un contrôleur de vue dans une scène à une sortie d'un contrôleur de vue dans une scène différente. Je ne crois pas que ce soit possible, peut-être parce que la machine de storyboard peut ne pas avoir toutes les scènes dans un storyboard chargé en même temps.

vous demandez probablement cela parce que vous voulez transmettre des informations d'un contrôleur de vue à un autre alors que vous vous déplacez d'une scène à l'autre. La façon de faire cela lorsque vous travaillez avec des storyboards est de surcharger -prepareForSegue:sender: dans un ou deux contrôleurs de vue affectés par la séquence. L'objet UIStoryboardSegue fourni dans le paramètre segue possède les propriétés sourceViewController et destinationViewController , ainsi qu'une propriété identifier . Vous pouvez utiliser ces propriétés pour identifier la séquence qui est sur le point de transférer des données entre les contrôleurs de vue.

le blog de Ray Wenderlich a un joli tutoriel en deux parties sur l'utilisation des storyboards qui peuvent vous aider:

  • Partie 1 couvre la mise en place d'un projet de storyboard, l'ajout de scènes, et la création de séquences.

  • Partie 2 traite avec l'aide de enchaîne à la transition entre les scènes, y compris le prepareForSeque méthode mentionnés ci-dessus.

iOS 5 permet aux contrôleurs de vues multiples d'être actifs dans la même scène (bien que l'un d'eux devrait toujours être en charge), donc une seule scène dans votre storyboard peut avoir plusieurs contrôleurs. Vous pouvez utiliser des prises pour connecter ces contrôleurs les uns aux autres, et vous pouvez configurer ces connexions de la même manière que vous l'avez fait dans IB: control-drag d'un contrôleur à l'autre dans la même scène. La liste de sortie habituelle s'ouvrira pour vous laisser choisissez la sortie à connecter.

7
répondu Caleb 2011-11-22 20:24:51

la clé pour utiliser plusieurs contrôleurs dans une scène (ce que je crois que vous êtes après ici) est d'utiliser l'objet mystérieux de la liste des objets dans IB pour représenter l'autre contrôleur de vue et d'accrocher ses sorties.

Cette réponse Comment créer un affichage personnalisé contrôleur de conteneur à l'aide de storyboard dans iOS 5 devrait aider je l'espère. La réponse fournit également un exemple d'application qui est très utile.

5
répondu Matt__C 2017-05-23 11:52:55

le problème avec la réponse de @Ben (autrement raisonnable) est qu'elle ne fonctionne qu'à un niveau de nidification. Au-delà de cela, il faudrait que chaque VC subséquent soit personnalisé pour sauver le contrôleur de la vue de nidification dans prepareForSegue.

pour résoudre ceci, j'ai passé trop de temps à explorer un index basé sur NSObject que vous pourriez ajouter au Storyboard, lier à une scène, et qui enregistrerait alors son parent VC dans un index global, basé sur le type et le restaurationid. Cela fonctionne / peut fonctionner, mais est trop d'effort en fin de compte, et nécessite encore le processus en deux étapes de liaison visuelle, et la recherche programmatique vers le haut.

pour moi, la solution la plus simple et la plus générale est de descendre paresseusement la hiérarchie du contrôleur de vue

dans mon projet de test simple, j'ai ajouté les lignes suivantes à viewDidLoad:

    self.left.data = [
        "Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro.",
        "De carne lumbering animata corpora quaeritis." ]

left est défini comme:

lazy var left:CollectionViewController = { [unowned self] in
    return self.childViewControllerWithId("Left") as! CollectionViewController }()

et childViewControllerWithId est défini comme suit:

extension UIViewController {
    func childViewControllerWithId(rid:String) -> UIViewController? {

        // check immediate child controllers
        for vc in self.childViewControllers as! [UIViewController] {
            if vc.restorationIdentifier == rid { return vc }
        }

        // check nested controllers
        for vc in self.childViewControllers as! [UIViewController] {
            if let vc = vc.childViewControllerWithId(rid) {
                return vc
            }
        }

        assert(false, "check your assumptions")
        return nil
    }
}

notez que vous pouvez faire d'autres variantes find basées sur le type, si besoin est. Notez également que ce qui précède exige que vous définissiez l'id de restauration dans le fichier Storyboard. Si vous n'aviez pas d'instances répétées du même contrôleur de vue, alors utiliser type serait plus facile.

et pour énoncer ce qui est, espérons-le, évident, vous n'avez pas besoin d'implémenter prepareForSegue, ni d'utiliser le chargement paresseux, il suffit d'appeler find(...) .

4
répondu Chris Conover 2015-03-13 23:43:40