[Résolu] NSViewController : [self setView:self.view], une absurdité nécessaire?

berfisberfis Membre
juin 2013 modifié dans API AppKit #1

Bonjour,


 


Je dérive NSViewController de la façon suivante:



@interface Door : NSViewController
...

@implementation Door

- (id)initWithCell:(MapCell *)aCell
{
self = [super initWithNibName:@Door bundle:nil];
if (self) {

[self setView:self.view]; // (!)
...

Mais tant que je ne fais pas appel à  self.view, même de la manière la plus inepte (un NSLog par exemple), ma vue n'est pas chargée, et ceci bien que l'outlet "view" du File Owner soit correctement fixé. D'où la ligne [self setView:self.view], qui paraà®t absurde mais qui fait que cela fonctionne...


 


Pourriez-vous m'indiquer le passage de la doc que j'ai manqué?


 


Merci!


 


Réponses

  • samirsamir Membre

    Bonjour,


     


    t'a mis quoi comme classe du file's owner de xib Door.xib ?il faut le mettre a NSViewController.


  • Le File Owner est "Door". J'ai d'autres IBOutlets dans mon contrôleur dérivé, si je déclare le NSViewController standard, je n'y aurai plus accès...


  • AliGatorAliGator Membre, Modérateur
    C'est normal que la vue ne soit pas chargée !!!!
    Et il ne faut surtout pas forcer son chargement comme tu fais.

    Le init que tu implémentes c'est le init du ViewController. Ce n'est pas parce que le UIViewController est instancié (avec init) que la vue qu'il gère est instanciée dans la foulée. La vue n'est chargée que quand ton UIViewController veut l'afficher à  l'écran.

    Quand tu demandes à  ce que ton UIViewController s'affiche à  l'écran, alors si la vue n'est pas chargée il va la charger, mais seulement à  ce moment là  (c'est ce qu'on appelle du lazy-loading).

    Les méthodes utiles de UIViewController attachées à  ce mécanisme :
    - isViewLoaded : te dit si la vue a déjà  été chargée ou pas. Si isViewLoaded est à  NO, la vue est à  nil car pas encore chargée en mémoire (le XIB n'a pas encore été désarchiver pour construire la vue et ses IBOutlets etc)
    - L'accesseur self.view est lazy-loaded, c'est à  dire que la première fois que tu l'appelles, s'il voit qu'il n'a pas chargé la vue il va la charger (via le XIB par exemple, ou via loadView...) la première fois
    - loadView : Méthode appelée par le UIViewController pour charger la vue par code
    - viewDidLoad : Méthode appelée par le UIViewController une fois que la vue est chargée, par exemple une fois qu'il a chargé la vue via le XIB et créé la vue, ses sous-vues et connecté ses IBOutlets.


    Du coup, pour ton cas, si tu as besoin de faire des trucs que quand ta vue est chargée, plutôt que de forcer son chargement avec ta "ligne absurde" que tu as mise, il faut plutôt que tu déplaces ton code (qui manipule les éléments de la view et les IBOutlets) dans viewDidLoad (appelé quand la vue est chargée) et pas dans le init (appelé quand le VC est initialisé mais la vue pas forcément chargée)
  • Et... voila pourquoi ça ne marchait pas. Merci AliGator. J'avais l'enchaà®nement suivant:


    1. Initier le contrôleur


    2. Selon la valeur d'une propriété, insérer ou non des sous-vues (définies par code) dans la vue principale


    3. Placer une image dans une sous-vue de la vue principale (définie dans le nib, avec outlet)


     


    Si le point 2 était "OUI", la vue principale s'affichait, avec ses sous-vues et son image.


    Si le point 2 était "NON", la vue principale ne s'affichait pas. Ni bien sûr l'image de la sous-vue.


     


    Donc en fait j'ai besoin immédiatement de la vue principale. Le fait d'insérer des sous-vues provoquait le chargement de l'image, mais curieusement le setImage de la sous-vue ne le faisait pas!


     


    Déplacer le code, moi je veux bien mais je me demande où je le mettrai, étant donné que -viewDidLoad existe peut-être sur iOS, mais il n'y a pas d'équivalent sur MacOS...


     


    Si je substitue "loadView" à  ma ligne absurde (qui finalement était plus une erreur de sélecteur, mais pas de fait), je ne verse donc pas dans l'hérésie?


  • AliGatorAliGator Membre, Modérateur
    Ah oui pardon tu es sous OSX... L'équivalent est sans doute plutôt du côté de la méthode awakeFroNib.

    Enfin faut relire les Programming Guides associés (View Controller Programming Guide et tout) tout est détaillé dedans mieux que je ne le ferais moi-même.
  • J'ai découvert ça, (très) péniblement, à  mes débuts mais avec un WindowController et le résultat est exactement le même : tant que tu n'appelles pas la fenêtre elle est à  0x0. ça peut se déduire, mais il faut y penser, quand on lit la doc qui explique le chargement d'un fichier .nib  qui dit que


     


    If you specify a nib file when creating the view controller, that nib file is loaded automatically when you try to access the view controller's view


     


    Donc c'est de tenter d'accéder à  la vue qui la fait naitre ...


     


  • Merci vous trois!


    @laudema: il y a des milliers de pages de doc, maintenant il faut encore lire entre les lignes...


     


    "If you specify a nib file when creating the view controller, that nib file is not loaded until you try to access the view controller's view."


     


    aurait peut-être été plus indiqué, mais moins "positive attitude"...

  • Oui c'est le genre de renseignement qu'on trouve une fois qu'on a déjà  la réponse :( . En ce qui me concerne c'est StackOver Flow qui avait la solution a "pourquoi la foutue fenêtre de ce p*t#in de controller n'a pas pris en compte mon message", j'y ai passé des heures à  comprendre, c'était mes débuts et je m'en souviens encore... J'en ai retenu qu'il faut être circonspect quand on diverge de l'usage recommandé.


     


    Mais bon c'était pour la part : "pouvez vous me dire quel passage de la doc j'ai manqué" de ta question ;)


Connectez-vous ou Inscrivez-vous pour répondre.