Vues personnalisées avec Storyboard

96

Dans les écrans complexes (View Controllers), j'avais l'habitude de séparer le tout en plus petits morceaux (je les appelle widgets). Ces widgets se composent essentiellement d'un MyWidget.het d'un MyWidget.mfichier ainsi que d'un MyWidget.xibfichier, où l'élément racine est a UIViewet la classe MyWidget est le propriétaire du fichier de l'UIView. Dans l'init de ce widget, je fais un loadNibNamed.

Dans mon View Controller, je fais ensuite un [[MyWidget alloc] init], que j'ajoute à la vue principale de View Controller en tant que sous-vue. Ceci, jusqu'à présent, fonctionne parfaitement.

Je me demande maintenant comment faire la même chose avec le storyboard, car je ne peux pas vraiment commencer à glisser UIViewquelque part, je dois toujours commencer par un UIViewController, ce que je ne veux pas.

S'il n'y a aucun moyen possible de le faire avec un Storyboard, puis-je simplement le faire à l'ancienne, en utilisant le Storyboard pour mes écrans principaux et mes segments, et utiliser un fichier .xib séparé pour définir des vues personnalisées?

znq
la source
Souhaitez-vous créer des xibs pour vos contrôleurs de vue séparément et non dans le story-board?
tipycalFlow
Avez-vous trouvé une solution à cela?
aryaxt
@aryaxt: J'utilise un mélange de Storyboard et de xib. Storyboard pour les écrans principaux et xib avec seulement un UIView comme racine pour des vues complexes ou des widgets. Donc pas vraiment une réponse à ma question initiale (en utilisant le storyboard), mais en gros, je fais exactement la même chose que j'ai déjà fait avant.
znq
ces jours-ci, il suffit d'utiliser une vue conteneur , c'est vraiment aussi simple que cela. stackoverflow.com/questions/23399061/…
Fattie

Réponses:

189

Le fait de placer le widget / la vue dans un fichier .xib séparé fonctionne, et est particulièrement approprié si vous souhaitez référencer cette même vue à partir de plusieurs contrôleurs de vue.

Cependant, vous souhaitez parfois voir la vue / widget supplémentaire dans le même storyboard, et c'est possible. Voici comment procéder:

  1. Sélectionnez votre contrôleur de vue dans IB (cliquez sur la barre noire sous la vue), puis faites glisser un UIView de la bibliothèque d'objets dans la barre noire:

    entrez la description de l'image ici

  2. Lorsqu'une vue est dans la barre noire, elle est instanciée comme n'importe quelle autre vue dans IB, mais n'est tout simplement pas ajoutée à votre hiérarchie de vues tant que vous ne le faites pas dans le code. Modifiez la classe de la vue pour qu'elle corresponde à votre propre sous-classe si nécessaire:

    entrez la description de l'image ici

  3. Vous pouvez le connecter à votre contrôleur de vue comme vous le feriez avec n'importe quelle autre vue: entrez la description de l'image ici

  4. La vue ajoutée apparaît dans la structure de votre document et vous pouvez également y connecter des actions et des références:

    entrez la description de l'image ici


Maintenant, le problème qui persiste est que vous ne pouvez pas réellement voir la vue, quel que soit le nombre de fois que vous essayez de cliquer ou de double-cliquer, ce qui irait à l'encontre de l'objectif de la placer dans le même storyboard. Heureusement, je connais deux solutions de contournement.

La première solution de contournement consiste à faire glisser la vue de la barre noire vers la vue de votre contrôleur de vue, à la modifier, puis à la faire glisser dans la barre noire une fois que vous avez terminé. C'est gênant mais fiable.

L'autre solution de contournement est plus délicate, mais je la préfère car elle me permet de voir toutes mes vues en même temps:

  1. Faites glisser un UITableView de la bibliothèque d'objets dans votre vue nouvellement ajoutée.

  2. Faites ensuite glisser un UITableViewCell dans ce UITableView.

    entrez la description de l'image ici

  3. Une fois que vous faites cela, votre vue apparaît comme par magie sur le côté, mais vous avez un UITableView que vous ne voulez pas. Vous pouvez soit le redimensionner à 0x0, soit le supprimer et votre UIView restera (généralement) toujours visible.

  4. Parfois, la vue secondaire sera à nouveau masquée dans IB. Vous pouvez répéter les étapes ci-dessus si vous avez supprimé l'UITableView, ou si l'UITableView est toujours dans la hiérarchie, il vous suffit de cliquer sur UITableViewCell et la vue réapparaîtra.

La deuxième méthode fonctionne pour UIViews mais pas très bien pour UIToolbars et est impossible pour UIButtons, donc la solution la plus propre que j'ai trouvée lorsque vous avez besoin d'inclure beaucoup de sous-vues différentes consiste à attacher un seul UIView secondaire à votre contrôleur de vue en tant que conteneur qui ne s'affiche jamais, mettez toutes vos vues secondaires là-dedans et utilisez l'astuce UITableViewCell pour rendre tout visible. Je redimensionne mon UITableView factice à 0x0 pour le rendre invisible. Voici une capture d'écran de tout cela:

entrez la description de l'image ici

nioq
la source
Mars 2013, je n'avais pas besoin de faire cela - vous devriez ignorer complètement la barre noire et faire glisser / déposer votre vue directement dans la vue principale, et cela fonctionne bien (Xcode 4.5+)
Adam
Est-il possible de réutiliser cet uivew personnalisé sur le même ViewController - Si j'ex. besoin de deux uivews personnalisés - Et si c'est comment?
Morten Gustafsson
2
Dang, je préfère simplement créer un xib séparé. Je ne me souviendrai probablement pas de tout cela lorsque je devrai mettre à jour l'application dans 6 mois.
Sandy
Bien que ce soit une réponse géniale, j'ai accidentellement trouvé une autre meilleure façon de penser. Lors du raccordement de prises à des composants de vue réels. Si vous survolez un peu un composant d'une telle vue intérieure, il apparaît pour une sélection plus facile. Ensuite, vous le voyez sur le storyboard ...
Oded Ben Dov
7
Bien que ce soit une réponse historique incroyablement admirable, elle est maintenant totalement dépassée. Apple a résolu le problème en introduisant des "vues de conteneur", qui sont maintenant la chose centrale et de base que vous faites lorsque vous créez des applications - tout comme une "vue de conteneur" tout le temps. Dieu merci, c'est maintenant très facile!
Fattie
11

Si vous cherchez simplement à créer vos contrôleurs de vue ailleurs (et pas dans votre story-board), il existe un moyen assez simple d'accomplir cela:

1) Créez vos CustomViewControllers ( abcdControllerdans le code que j'ai essayé) avec leurs xibs individuels comme d'habitude.

2) Ajoutez un UIViewController(ou ce qui était la superclasse de votre CustomViewController) au story-board.

3) Définissez CustomClass sur au CustomViewControllerlieu de UIViewControllercomme indiqué ici:

entrez la description de l'image ici

4) Enfin, dans votre viewDidLoad, chargez la personnalisation xibet vous avez terminé.

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSBundle mainBundle] loadNibNamed:@"abcdController" owner:self options:nil];
    // Do any additional setup after loading the view from its nib.
}
tipycalFlow
la source
3
Merci pour votre réponse très détaillée, mais je ne recherche pas en fait un contrôleur de vue personnalisé, mais une vue personnalisée (un widget), qui est ajoutée à un UIViewController standard. Le contrôleur de vue n'est donc pas le problème, mais je me demandais quelle était la meilleure approche pour créer des widgets personnalisés. Soit A) faites-le comme avant, avec un fichier .xib ou B) une autre approche que je ne connais pas encore :-)
znq
1
Hmm ... je pense que j'ai ce que tu veux. En gros, vous souhaitez gérer plusieurs vues avec le même contrôleur, non? Je ne peux pas penser à un autre moyen que loadNibNameddans ce cas ... XO
tipycalFlow
Cela a résolu ce problème pour moi: stackoverflow.com/questions/11047991/... Cependant, au lieu de viewDidLoad, j'ai utilisé loadView ...
Morkrom
1
Juste pour répéter, c'est tout (Dieu merci!) Totalement obsolète maintenant que les vues de conteneurs sont ici. Cliquez simplement sur une vue de conteneur et tout est fait
Fattie
1

Je pense que vous pouvez faire quelque chose comme ça pour obtenir une instance de viewcontroller spécifique à partir de Storyboard et utiliser la vue par-dessus.

ex:
MyViewController* myViewController = [[UIStoryboard storyboardWithName:@"Main"  bundle:nil] instantiateViewControllerWithIdentifier:@"myViewController"];
UIView* view = myViewController.view; //Get the view from your StoryBoard.

J'espère que cela t'aides

Merci Vijay

vijay_hrd
la source