NSViewController [Résolu]

novembre 2012 modifié dans API AppKit #1
J'ai commencé à  plancher le sujet des NSViewController pour refaire mon programme Electro Suite. J'envisage en effet de faire comme pour les Préférences Systèmes d' OS X, avec une fenêtre principale, affichant une box contenant, au lancement, tous les boutons des divers modules de calcul. En plus, un bouton hors de la box (peut être alors dans une barre d'outils) permettant à  tout moment de revenir à  cet écran. Puis chaque bouton affichera dans le cadre le module de calcul sélectionné.



J'ai trouvé un exemple qui propose de créer dans le fichier NIB principal des objets NSViewController pour chaque vue (au niveau d'Interface Builder), de fixer leur fichier NIB dans l'inspecteur des propriétés, fichiers constitués d'une vue contenant tous les éléments de contrôle. Chaque objet NSViewController aura une Outlet dans AppDelegate.h Puis, dans le code, pour afficher une vue on fait


<br />
- (IBAction)switchView1:(id)sender<br />
{<br />
	NSView *view = [testView1Controller view];<br />
  <br />
	[box setContentView:view];<br />
}<br />


avec testView1Controller désigant l'outlet créé pour l'objet NSViewController de la vue considérée et box pour l'outlet de la NSBox.



Alors, je retranscris tel que je l'ai compris. Est-ce que cette façon de faire est correcte ?



Ensuite, si cette solution marche, elle serait assez lourde dans mon cas car il me faudrait alors une instance par outil plus une, pour le panneaux de boutons d'acceuil. De plus, au démarrage, une instance de chaque panneau serait créé, même pour ceux ne servant pas dans la session.



Serait-il alors possible de créer l'instance par code en faisant


<br />
- (IBAction)switchView1:(id)sender<br />
{<br />
<br />
ViewController1 *testView1Controller=[[NSController view alloc]initWithNibName @&quot;testView1&quot;] //ViewController étant une classe héritée de NSViewController contenant le code de la vue, avec ses contrôles et tout<br />
NSView *view = [testView1Controller view];<br />
<br />
[box setContentView:view];<br />
}<br />

Réponses

  • CéroceCéroce Membre, Modérateur


    Chaque objet NSViewController aura une Outlet dans AppDelegate.h


    Non, pas une outlet. Une outlet est un pointeur vers un objet du nib.

    Un simple pointeur de NSViewController suffit.



    <br />
    - (IBAction)switchView1:(id)sender<br />
    {<br />
    	NSView *view = [testView1Controller view];<br />
    	[box setContentView:view];<br />
    }<br />
    


    Alors, je retranscris tel que je l'ai compris. Est-ce que cette façon de faire est correcte ?




    ça devrait fonctionner, mais utiliser une NSBox n'est pas forcément nécessaire. Tu peux ajouter la vue gérée par le ViewController à  n'importe quelle vue en utilisant -[NSView addSubview:].




    Ensuite, si cette solution marche, elle serait assez lourde dans mon cas car il me faudrait alors une instance par outil plus une, pour le panneaux de boutons d'accueil.


    Au contraire, ce n'est pas lourd. Certes, tu vas devoir créer une classe et un xib pour chaque panneau, mais tout ce qui concerne un panneau sera isolé dans une seule classe. Cette ségrégation va simplifier l'architecture de ton appli.

    En fait, ton cas est même plus simple qu'habituellement, puisque tu n'as pas de valeurs à  passer d'un view controller à  un autre.




    De plus, au démarrage, une instance de chaque panneau serait créé, même pour ceux ne servant pas dans la session.


    Non, ce n'est pas nécessaire. Seul le panneau actuellement affiché a besoin d'être présent en mémoire.

    ça donnerait quelque chose comme ça:


    <br />
    @interface AppDelegate: NSObject &lt;NSApplicationDelegate&gt;<br />
    @property (weak, nonatomic) IBOutlet NSWindow *window;<br />
    @property (strong, nonatomic) NSViewController *currentViewController;<br />
    @end<br />
    





    <br />
    @implementation AppDelegate<br />
    <br />
    @synthesize currentViewController = _currentViewController;<br />
    - (void) setCurrentViewController:(NSViewController *)newViewController<br />
    {<br />
    	NSView *contentView = (NSView *)[self.window contentView];<br />
    <br />
    	// Retirer la vue actuelle<br />
    	if(_currentViewController)<br />
    		[self.currentViewController.view removeFromSuperview];<br />
    <br />
    	// Retenir le nouveau view controller<br />
    	_currentViewController = newViewController;<br />
    <br />
    	// Ajouter la nouvelle vue<br />
    	_currentViewController.view.frame = contentView.bounds;<br />
    	[contentView addSubview:_currentViewController.view];<br />
    }<br />
    <br />
    - (IBAction) ohmButton:(NSButton *)sender<br />
    {<br />
    	self.currentViewController = [[OhmViewController alloc] initWithNibName:@&quot;OhmViewController&quot; bundle:nil];<br />
    }<br />
    <br />
    - (IBAction) filtresButton:(NSButton *)sender<br />
    {<br />
    	self.currentViewController = [[FiltresViewController alloc] initWithNibName:@&quot;FiltresViewController&quot; bundle:nil];<br />
    }<br />
    <br />
    @end<br />
    
  • Merci beaucoup. Je vais donc faire des essais sur une application-test et, si j'y arrive, je ferais la même chose sur mon programme
  • J'ai donc réussi à  faire ce que je voulais, à  savoir une fenêtre unique et des vues diverses en fonction de l'outil sélectionné. Seulement, il y a un petit problème : dans la version multifenêtres, je surchargeais la méthode windowDidLoad pour y mettre du code d'initialisation (instanciation d'objets, et affichages par défaut) . Or, dans une classe héritée de NSViewController, je n'ai pas cette méthode. J'ai par contre une méthode initWithNibName: Bundle: Mais en la surchargeant, je peux faire des calculs, instancier des objets, mais pas agir sur les contrôles de la vue. Ce qui peut se comprendre, la méthode s'exécute avant l'affichage de la vue et donc, on ne peux pas agir sur des objets qui ne sont pas encore instanciés (en l'occurrence, les contrôles de la vue). Que dois-je faire alors ?



    Existe-t-il une méthode équivalente à  windowDidLoad que je pourrai surcharger ?
  • CéroceCéroce Membre, Modérateur
    -awakeFromNib



    (Oui, c'est un peu introuvable dans la doc).
  • Merci beaucoup ! Ca marche nickel ! A bientôt pour le prochain écueil ...
Connectez-vous ou Inscrivez-vous pour répondre.