ARC : outlets déclarés en weak ou strong ?

muqaddarmuqaddar Administrateur
novembre 2012 modifié dans Objective-C, Swift, C, C++ #1
Salut,



J'ai lu qu'il fallait déclarer ses outlets en weak avec ARC (notamment chez Ray Wenderlich).



Or, en utilisant le convertisseur ARC présent dans Xcode pour convertir un projet existant, Xcode me les passe en "strong" par défaut.



Pourquoi ?

Réponses

  • Bah déjà  il y a un truc que j'ai jamais compris, pourquoi sur iOS on déclare les outlet en retain alors que sur Mac c'est en assign et que dans tous les cas les outlet sont retenu par la vue parante tant qu'elle existe...
  • AliGatorAliGator Membre, Modérateur
    Bah ça ne m'étonne pas du tout que le convertisseur ARC ne remplace pas les IBOutlets déjà  existants de strong à  weak.

    Encore heureux je dirais, même.

    Car si tu as créé des propriétés strong et codé en conséquence, s'il te change la politique d'ownership comme ça sans te demander ça risque d'avoir de sacrées conséquences.



    On peut mettre les IBOutlets en weak ou en strong les deux fonctionnent et son valides.



    Bien sûr, si on utilise ARC, c'est quand même bien mieux de mettre ses IBOutlets en weak, j'ai déjà  expliqué pourquoi dans l'autre sujet (pour qu'il les relâche tout seul en cas de memory warning, parce que ça nous évite de les remettre à  nil grâce au ZWR, tout ça). Mais rien ne t'empêche de les garder en strong. Ou d'avoir mis un IBOutlet en assign avant pour une raison quelconque, et le passer en strong (parce qu'on compte à  un moment donné supprimer la vue pointée par l'IBOutlet de sa superview, pour la re-rajouter bien plus tard, mais sans qu'elle se release entre temps)...



    Bref, rien n'empêche de mettre des IBOutlets en strong ou en weak, que ce soit avec ou sans ARC. Les 4 configurations sont valides et justifiables. Ca dépend de ce dont tu as besoin. D'ailleurs, même avant ARC, il était conseillé de mettre tes IBOutlets en assign déjà  pour tous ceux qui pointaient sur des sous-vues de la vue principale de ton ViewController.



    Après, bien évidemment si tu actives ARC, tu as souvent intérêt à  passer tes @property(strong) IBOutlet en weak, car cela t'évite d'avoir à  les libérer et est plus adapté à  la plupart des situations de gestion mémoire. Mais c'est à  toi de le faire (et encore heureux que le convertisseur te laisse le faire au cas par cas) car chaque changement de memory policy / ownership peut avoir ses conséquences si elles ne sont pas réfléchies
  • muqaddarmuqaddar Administrateur
    'AliGator' a écrit:


    Bah ça ne m'étonne pas du tout que le convertisseur ARC ne remplace pas les IBOutlets déjà  existants de strong à  weak.

    Encore heureux je dirais, même.

    Car si tu as créé des propriétés strong et codé en conséquence, s'il te change la politique d'ownership comme ça sans te demander ça risque d'avoir de sacrées conséquences.




    En effet, c'est le cas. Ils étaient en retain.


    'AliGator' a écrit:


    On peut mettre les IBOutlets en weak ou en strong les deux fonctionnent et son valides.



    Bien sûr, si on utilise ARC, c'est quand même bien mieux de mettre ses IBOutlets en weak, j'ai déjà  expliqué pourquoi dans l'autre sujet (pour qu'il les relâche tout seul en cas de memory warning, parce que ça nous évite de les remettre à  nil grâce au ZWR, tout ça). Mais rien ne t'empêche de les garder en strong. Ou d'avoir mis un IBOutlet en assign avant pour une raison quelconque, et le passer en strong (parce qu'on compte à  un moment donné supprimer la vue pointée par l'IBOutlet de sa superview, pour la re-rajouter bien plus tard, mais sans qu'elle se release entre temps)...



    Bref, rien n'empêche de mettre des IBOutlets en strong ou en weak, que ce soit avec ou sans ARC. Les 4 configurations sont valides et justifiables. Ca dépend de ce dont tu as besoin. D'ailleurs, même avant ARC, il était conseillé de mettre tes IBOutlets en assign déjà  pour tous ceux qui pointaient sur des sous-vues de la vue principale de ton ViewController.




    ça, ça m'avait échappé, les miens ont toujours été strong (retain).


    'AliGator' a écrit:


    Après, bien évidemment si tu actives ARC, tu as souvent intérêt à  passer tes @property(strong) IBOutlet en weak, car cela t'évite d'avoir à  les libérer et est plus adapté à  la plupart des situations de gestion mémoire. Mais c'est à  toi de le faire (et encore heureux que le convertisseur te laisse le faire au cas par cas) car chaque changement de memory policy / ownership peut avoir ses conséquences si elles ne sont pas réfléchies




    ok, ok, effectivement, je pense en passer 95% en weak.



    J'ai pas bien compris ton exemple où il est conseillé de les mettre en strong.

    Tu peux développer stp ? Oui, donne moi un bel exemple.
  • AliGatorAliGator Membre, Modérateur
    novembre 2012 modifié #5
    Exemple très simple, celui que j'ai (apparemment mal) expliqué plus haut : si tu as un IBOutlet vers une UIView que tu supprimes de la hiérarchie de vues pendant la durée de vie de l'appli, pour la réajouter à  la hiérarchie de vue plus tard
    @interface TotoViewController : UIViewController<br />
    @property(strong) IBOutlet UIView* helpView;<br />
    -(IBAction)toggleHelp;<br />
    @end<br />
    <br />
    @implementation TotoViewController<br />
    -(IBAction)toggleHelp<br />
    {<br />
       if (&#33;self.helpView.superview)<br />
       {<br />
    	  // Help is not shown yet, add it to the view hierarchy<br />
    	  [self.view addSubview:self.helpView]; // si helpView était weak, il aurait eu le temps de se dealloc&#39;d avant d&#39;arriver à  ce code et serait alors nil d&#39;ici là <br />
       } else {<br />
    	  [self.helpView removeFromSuperview]; // si helpView était weak, elle serait alors dealloc&#39;d ce que je ne veux pas<br />
       }<br />
    }<br />
    @end
    
    Bon, là  j'ai pris l'exemple basique d'une vue d'aide, et bien sûr j'aurais pu à  la place laisser la vue toujours en subview et faire basculer sa propriété hidden de YES à  NO. Mais c'est juste pour te montrer le principe. Ca peut aussi être une vue qui sert de menu, qu'on veut afficher avec une transition, etc... et donc où juste le changement de hidden ne serait plus applicable.



    Par exemple, un autre cas similaire, si on veut "retourner" une vue pour afficher une autre vue qui semblerait être son "dos". On utilise alors les méthodes genre [font=courier new,courier,monospace][UIView transitionFromView:vueA toView:vueB][/font] qui font une animation de retournement, qui va supprimer la vueA de la hiérarchie des vues et ajouter la vueB à  la place. Et quand tu re-retournes pour réafficher le "recto", ça va à  l'inverse supprimer vueB de sa superview pour réajouter vueA à  la place. Pendant toute cette opération, il faut que vueA et vueB continuent d'exister en mémoire et ne soient pas released, au risque sinon de disparaà®tre de la mémoire et ne plus exister. Il faut donc absolument qu'elles soient strong et pas weak.



    De manière générale, toute vue qui à  un moment donné peut être retirée des sous-vues (ou sous-sous-*-sous-vues) de la vue principale de ton ViewController doit être en strong pour ne pas disparaà®tre quand elle ne sera plus retenue par la vue principale.



    J'utilise ce cas aussi pour certains de mes XIBs dans lesquels je n'ai pas que la UIView de mon ViewController comme "top level object" (à  côté du File's Owner et du First Responder), mais aussi parfois d'autres vues que je garde de côté avec un IBOutlet pour les ajouter par code plus tard.
  • muqaddarmuqaddar Administrateur
    Bon, j'ai bien compris cette fois-ci.

    Les exemples sont clairs. Merci Ali.



    Je vais modifier légèrement le titre du sujet.
  • muqaddarmuqaddar Administrateur
    novembre 2012 modifié #7
    Je reviens à  la charge car j'ai un problème de conversion depuis hier.



    J'essaie de convertir mon projet au fur et à  mesure en ARC.

    Dés que je touche à  un VC, je le passe en ARC grâce à  la conversion auto de Xcode.



    Tout a bien marché pour les 3 premiers VC.

    Mais pas les suivants.



    Ma méthode:



    1) Je sélectionne mon nouveau fichier à  convertir.



  • AliGatorAliGator Membre, Modérateur
    Je me demande s'il ne s'emmêle pas les pinceaux si tu ne convertis que certains fichiers et pas d'autres, l'outil de conversion automatique doit un peu être perdu je pense entre les fichiers déjà  ARC et ceux non-ARC peut-être.



    Essaye de supprimer les DerivedData de ton projet pour forcer à  reconstruire tout l'index. Et quitte et relance Xcode ensuite. Des fois ça aide un peu.

    (Va dans l'Organizer, onglet "Projects", sélectionne ton projet et clique sur "Delete" en face des DerivedData)
  • muqaddarmuqaddar Administrateur
    J'ai essayé en supprimant les DerivedData, C'est la même chose.

    (avec redémarrage Xcode)



    Je viens aussi d'essayer de convertir tous les fichiers à  la fois sans succès. image/sad.png' class='bbc_emoticon' alt=':(' />
  • AliGatorAliGator Membre, Modérateur
    novembre 2012 modifié #10
    Ah c'est déjà  plus embêtant alors.

    Et si tu crées un xcodeprojet bidon dans lequel tu ne mets que tes classes à  convertir et testes la conversion dessus ?

    Pour les isoler des autres qui semblent lui donner du fil à  retordre quoi
  • muqaddarmuqaddar Administrateur
    novembre 2012 modifié #11
    'AliGator' a écrit:


    Ah c'est déjà  plus embêtant alors.

    Et si tu crées un xcodeprojet bidon dans lequel tu ne mets que tes classes à  convertir et testes la conversion dessus ?

    Pour les isoler des autres qui semblent lui donner du fil à  retordre quoi




    Je crois que c'est la seule chose qu'il me reste à  faire ! ;-)
Connectez-vous ou Inscrivez-vous pour répondre.