Charger une sous-vue via interface builder

[SDK 10.6, Xcode 4.2]



Bonjour !



Voilà  mon (nouveau) problème image/crazy.gif' class='bbc_emoticon' alt=' B) ' /> ...



J'ai créé un couple NSViewController / fichier NIB.

Je les ai appelés HeaderViewController.



Je souhaiterais les ajouter dans ma fenêtre à  l'aide d'interface builder.



Par conséquent, dans IB, je modifie MainMenu.xib comme suit :
  • J'ajoute une "Custom View" dans ma fenêtre. Je laisse sa classe à  NSView.
  • J'ajoute un Object dans les objets associés au NIB (cube bleu, que j'ajoute dans la barre de gauche). Je renomme sa classe à  HeaderViewController.
  • Enfin, je connecte l'outlet view de HeaderViewController à  ma "Custom View". L'outlet view est semble-t-il fourni automatiquement par la class NSViewController. Dans ma classe HeaderViewController, je n'ai en effet aucun outlet view.


Quand je charge l'appli, rien ne s'affiche...

J'ai pourtant l'impression de faire les choses selon la logique Apple.

Des idées ? Un problème de timing entre les 2 NIB ?



Merci !



PS : Voilà  la méthode d'init de HeaderViewController
- (id)init<br />
{<br />
	NSLog(@&quot;Création d&#39;une instance de HeaderViewController&quot;);<br />
  <br />
	self = [super initWithNibName:@&quot;HeaderViewController&quot; bundle:nil];<br />
	if (self) {<br />
		// Initialization code here.<br />
	}<br />
  <br />
	return self;<br />
}<br />

Réponses

  • CéroceCéroce Membre, Modérateur
    mars 2013 modifié #2
    Non. C'est le NSViewController qui charge le nib, il ne peut donc pas être instancié dedans.
    1. Modifie la classe de Files's Owner à  HeaderViewController. Tu pourras alors tirer les outlets et actions.

      File's Owner est le propriétaire du fichier nib, c'est à  dire celui qui l'instancie.
    2. Instancie un HeaderViewController par le code:

    self.headerViewController = [[HeaderViewController alloc] initWithNibName:@&quot;HeaderViewController&quot; bundle:nil];<br />
    // Ajouter à  la fenêtre<br />
    [self.window.contentView addSubview:viewController.view];<br />
    
  • CéroceCéroce Membre, Modérateur
    'colas2' a écrit:

    - (id)init<br />
    {<br />
    	self = [super initWithNibName:@&quot;HeaderViewController&quot; bundle:nil];<br />
    <br />
    



    Evite de faire ça. Même si tu trouves idiot de passer le nom du nib quand tu crées ton HeaderViewController, le fait de passer ce nom permet d'utiliser des nib différents avec la même classe de view controller. Certes sur Mac, c'est moyennement utile, mais je le fais par exemple pour avoir des nib différents sur iPhone et sur iPad.
  • Merci !



    J'ai l'impression que de vouloir composer sa fenêtre avec plein de sous-vues (par exemple : header, main, etc.) n'est pas très adapté au fonctionnement de cocoa, et que j'ai plus intérêt à  construire ma fenêtre en un seul nib. Cela vous semble-t-il vrai ?
  • CéroceCéroce Membre, Modérateur
    mars 2013 modifié #5
    C'est plus simple et plus rapide, effectivement.



    Mais ce n'est pas l'approche conseillée: si la fenêtre comporte beaucoup de vues, ça fait autant d'outlets et d'actions, et le contrôleur devient très complexe. Scinder en plusieurs view controllers réduit cette complexité, mais demande plus d'expérience, puisqu'il faut passer le modèle d'un contrôleur à  l'autre. (Apple impose l'utilisation des view controllers sous iOS).
  • As-tu un lien qui explique cette technique de << passer[font=helvetica, arial, sans-serif] le modèle d'un contrôleur à  l'autre >> ?[/font]

    [font=helvetica, arial, sans-serif]Merci ![/font]
  • CéroceCéroce Membre, Modérateur
    mars 2013 modifié #7
    Non, je n'ai pas de doc, mais ça n'a rien de sorcier quand on connaà®t le MVC.



    Par exemple, si le modèle comporte un NSArray de Recettes, et qu'un view controller sert à  afficher la recette courante, il suffit de créer une propriété dans le view controller:
    @property (strong, nonatomic) Recette *recette;
    




    Et le contrôleur parent devra passer la recette pour l'afficher:
    NSUInteger indexRecette = 3;<br />
    self.recetteViewController.recette = [self.modele.recettes objectAtIndex:indexRecette];<br />
    




    Rien de compliqué, vraiment. Il faut juste passer les informations pertinentes pour le view controller enfant, et seulement celles-là .
  • HerveHerve Membre
    Je dirai comme Céroce : dans IB, sur la fiche d'identité de ton CustomView, remplace NSView par ta classe qui dérive (bien évidemment) de NSView. N'oublie pas d'écrire quelque chose dans la méthode graphique pour la voir à  l'écran (ne serait-ce qu'une couleur pour le background) sinon elle restera grise et tu ne la verras pas...



    Après c'est très simple... Si il y a beaucoup de vues, on peut écrire au sein d'une classe dérivant de NSView une méthode ajoutant des subView. Dans ce cas :

    - écrire une classe correspondant à  ces views.

    - créer les instances de cette classe et les faire afficher dans la classe dérivant de NSView (celle qui est reliée à  ton CustomView dans IB)



    Exemple dans mon TechnoDrive, pour la table de mixage :

    Dans le header de la NSView "mixTable" :
    <br />
    @class PanAndDelayView;<br />
    @class ChoAndFuzzView;<br />
    @class VolumeControl;<br />
    


    puis :
    <br />
    VolumeControl *volumeControls[15];<br />
        PanAndDelayView *panAndDelayControls[15];<br />
        ChoAndFuzzView *choAndFuzzControls[15];<br />
    




    dans le "init" :
    <br />
    for (int i = 0; i &lt; 15; i++){<br />
    		    [[volumeControls[i+2] initWithFrame:NSMakeRect((17 + (i * 73)), 336, 65, 130)]retain];<br />
    		    [[choAndFuzzControls[i+2] initWithFrame:NSMakeRect((17 + (i * 73)), 474, 65, 65)]retain];<br />
    		    [[panAndDelayControls[i+2] initWithFrame:NSMakeRect((17 + (i * 73)), 547, 65, 65)]retain];<br />
    	    }<br />
    




    et dans le drawRect :



    <br />
    for (int i = 0; i &lt; 15; i++){<br />
    	    [self addSubview:volumeControls[i]];<br />
    	    [self addSubview:panAndDelayControls[i]];<br />
    	    [self addSubview:choAndFuzzControls[i]];[/size][/font]<br />
    (...)}<br />
    
  • colas_colas_ Membre
    mars 2013 modifié #9
    Merci pour ta réponse bien détaillée image/wink.png' class='bbc_emoticon' alt=';)' />


    'Herve' a écrit:


    Je dirai comme Céroce : dans IB, sur la fiche d'identité de ton CustomView, remplace NSView par ta classe qui dérive (bien évidemment) de NSView.




    Je n'ai pas de classe qui dérive de NSView...

    Je n'ai qu'une classe qui dérive de NSViewController...
  • 'colas2' a écrit:


    Je n'ai pas de classe qui dérive de NSView...

    Je n'ai qu'une classe qui dérive de NSViewController...




    NSView pilotera un CustomView dans IB, NSViewController pilotera toute une fenêtre (remplie de NSView...), par exemple quand tu ouvres une fenêtre en plus de la fenêtre principale. Ce ne sont pas du tout les même classes.
  • HerveHerve Membre
    mars 2013 modifié #11
    Oups, je crois que j'ai confondu NSViewController (que je ne connais pas d'ailleurs je crois) avec NSWindowController dans ma réponse précédente...



    Vérification faite, je n'avais pas complètement tord néanmoins.
Connectez-vous ou Inscrivez-vous pour répondre.