[résolu] - viewDidLoad appelé avant la fin de - init ???

colas_colas_ Membre
juin 2015 modifié dans API UIKit #1

Hello,


 


Dans la série "les choses qu'il est bon de savoir", et bien, il est bon de savoir que la méthode - viewDidLoad peut être appelée avant que la méthode - init ait retourné self.


 


ça paraà®t fou mais apparemment c'est comme ça.


 


EDIT


boire ou coder, il faut choisir ;-)


 


 


 


Réponses

  • Tu t'es vu quand t'as bu ?

  • AliGatorAliGator Membre, Modérateur
    juin 2015 modifié #3
    Heu à  mon avis c'est une mauvaise interprétation de ta part d'une séance de Debug, ça, parce que c'est clairement pas normal.

    T'es sûr que t'as pas 2 instances de la même classe qui sont instanciées en même temps, et tu as le viewDidLoad de la 2ème alors que tu es encore dans le init de la première, par exemple ?

    Ou alors, c'est que tu as mal codé, ton init, en particulier que tu as utilisé les setters ou propriétés plutôt que les variables d'instances (le seul rare cas d'exception pour lequel il faut utiliser les ivars plutôt que les propriétés c'est dans le init, justement pour éviter les effets de bord que ça aurait d'appeler un "setter" avant d'avoir fini de s'initialiser).

    Swift empêche ce genre de problème de par sa construction et par le compilateur qui détecte ça, mais en Objective-C c'est tout à  fait possible d'écrire "self.view" en plein milieu du init et du coup d'avoir comme effet de bord que ça appelle viewDidLoad avant la fin du init, alors que tu n'es pas sensé appeler "self.view".

    Eventuellement dans ce cas il faudrait donc plutôt utiliser "_view", pour ne pas que ça appelle le getter de la propriété, car c'est un lazy-getter qui, si elle n'existe pas encore, va charger la vue depuis le XIB et appeler viewDidLoad, alors qu'accéder à  _view ne pose pas ce problème. C'est pour ça que dans un "init" il ne faut normalement jamais utiliser "self.xxx" mais plutôt "xxx" pour éviter ce genre d'effet de bord " d'autant que de toute façon "self" n'est pas fini d'initialiser, donc c'est une mauvaise idée d'appeler des méthodes dessus, que ce soit des vraies méthodes ou un appel d'un getter caché derrière un accès à  une propriété).

    Mais en pratique, vu comment UIViewController fonctionne, c'est de toute façon une très mauvaise idée d'accéder à  la "view" dans le init. Si tu as besoin de modifier des propriétés de ta vue, il faut le faire dans viewDidLoad, c'est à  dire seulement quand la vue sera chargée parce que le UIViewController voit que tu en as besoin, et pas dans init où elle n'est pas encore chargée et où y accéder va forcer son chargement trop tôt.
  • Je suis tombé sur ce cas et après google je suis tombé sur http://stackoverflow.com/a/4862772/1670830qui m'a confirmé ce cas.


  • AliGatorAliGator Membre, Modérateur
    Oui, parce que dans ton init tu appelles des méthodes à  effet de bord, sans doute en particulier des propriétés, comme expliqué dans ma réponse (que j'ai éditée entre temps)
  • OK, merci de m'avoir "rappelé" à  l'ordre. Voilà  mon code fautif:



    - (instancetype)init
    {
    self = [super initWithNibName:NSStringFromClass([self class])
    bundle:nil] ;

    if (self)
    {
    /*
    We need the frame to create other elements
    */
    CGRect frame ;
    frame = CGRectMake(kXCoordinate, 0, kLengthSearchBar, self.view.frame.size.height) ;

    _otherUIElement = [[SomeUIElement alloc] initWithFrame:frame] ;

    /*
    We place the search bar
    */
    if (self.contentView)
    {
    [self placeComponents] ;
    }

    }


    return self;
    }

    En fait, c'est l'appel `self.view.frame.size.height` qui lance le viewDidLoad.


  • AliGatorAliGator Membre, Modérateur
    Bingo, comme ma boule de cristal avait prédit, donc, un accès à  self.view dans ton init, ce qui n'est pas du tout une bonne idée.

    La totalité de ton code que tu as placé dans le "if (self) { ... }" devrait aller entièrement dans le viewDidLoad, elle n'a rien à  faire dans le init du ViewController puisque la totalité de ce que tu fais dans ce code est de la création d'UI et d'ajout de view dans ta UIView, donc faut d'abord attendre qu'elle soit chargée.
  • Tu l'as achetée où ta boule Ali ;-) ?


  • AliGatorAliGator Membre, Modérateur
    C'est un dénommé "Phil Ing" qui me l'a offerte.
  • Je le connais aussi mais la boule qui m'a filée marche moins bien que la tienne ;-)


  • Phil se nourrit d'expérience donc ça viendra. :)


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