weakself, strongself et block

GeoffreyGeoffrey Membre
janvier 2015 modifié dans API UIKit #1

Hello,


 


Petite question aux maitres :)


 


Dans les completions blocks, j'avais pour habitude d'utiliser des weak self comme ca :



__weak typeof(self) weakSelf = self; // ou weakifySelf(weakSelf);

[self doABlockOperation:^{
weakself.qqchose etc...
    }
}];

Mais j'ai vu dans des libs internes que certains font :



__weak typeof(self) weakSelf = self; // ou weakifySelf(weakSelf);

[self doABlockOperation:^{
strongifySelf(strongSelf, weakSelf);
strongSelf.qqchose etc...
    }
}];

Et je me demandais si c'était quelque chose à  faire systématiquement (genre une meilleure pratique).


 



Réponses

  • amadehamadeh Membre
    janvier 2015 modifié #2

    Non ce n'est pas une meilleure pratique, ça dépend de ton contexte et de ce que tu veux faire.


     


    Si tu veux garder une référence sur ton objet self alors le strongify va te permettre d'éviter que ton self soit releasé.


     


    Tu fais un weakify si ça ne te gêne pas que ton self soit releasé. Comme les appels sur nil ne provoquent pas de crashs, si ton objet devient nil au début de ton completion block, alors pas de crashs.


  • AliGatorAliGator Membre, Modérateur
    Effectivement en fait faut juste avoir conscience que si tu utilises ton weakSelf directement dans le bloc ça ne l'empêche pas d'être release entre deux lignes du code qui est à  l'intérieur du bloc ou même avant ton bloc


    Rebasculer sur une variable strong (strongSelf) permet de s'assurer que l'objet sera retenu par la variable strong pendant la durée de vie de cette variable (autrement dit ici entre le début et la fin du bloc).


    Si dans ton code du bloc tu ne fais que des appels de méthode sur weakSelf c'est peut être pas si grave, les premières méthodes vont s'exécuter et en plein milieu si le code est interrompu par un autre thread qui supprime l'objet quand ça va revenir au reste de ton code dans ton bloc weakSelf sera passé à  nil entre temps, et faire des appels de métappels restants sur nil n'a aucun effet. Cependant selon ton contexte du coup la moitié des méthodes se seront exécutées mais pas l'autre moitié et selon ton cas ça peut ne pas t'arranger...


    D'où l'intérêt de s'assurer que l'objet va exister entre le début et la fin du bloc (pas passer à  nil en plein milieu) avec strongSelf.



    Autre truc qui peut être à  faire suivant le contexte c'est une fois que tu as prévu un strongSelf dans ton bloc, encadrer le reste du code de ton bloc dans un "if (strongSelf) {...}" pour ne pas exécuter le code qui l'objet weakSelf est passé à  nil avant que le bloc ne soit exécuté, genre si l'objet à  été détruit entre temps c'est pas la peine d'appeler des méthodes pour rien. Surtout si tu as des méthodes dans ton qui sont appellés sur autre chose que self et donc sont exécutées même si weakSelf est passé à  nil... alors que tu voudrais qu'elles ne s'exécute pas car ça sert à  rien (voire a des effets secondaires) dans ce cas.



    Bref selon ce que ton code dans le bloc fait c'est nécessaire ou pas. Faut avoir conscience de ce qui peut arriver surtout pour savoir dans quel cas utiliser ce strongSelf voire ce "if".
  • Ok merci !


     


    Et est ce que ca porte préjudice à  qqchose (perfs?) si j'utilise un strongself dans le bloc tout le temps ?


  • AliGatorAliGator Membre, Modérateur
    Non.
  • Joanna CarterJoanna Carter Membre, Modérateur



    __weak typeof(self) weakSelf = self; // ou weakifySelf(weakSelf);

    [self doABlockOperation:^{
    strongifySelf(strongSelf, weakSelf);
    strongSelf.qqchose etc...
        }
    }];

    Et je me demandais si c'était quelque chose à  faire systématiquement (genre une meilleure pratique).




     


    Moi, je trouve ces macros vraiment affreux, ou, peut-être c'est le code qui me gêne.


     


    C'est pas du tout évident d'où viennent les variables strongSelf et weakSelf.


     


    Je préfère le code plus lucide, voir explicite, comme :



    __weak typeof(self) weakSelf = self;

    [self doBlockOperation:^
    {
    typeof(weakSelf) strongSelf = weakSelf;

    if (strongSelf)
    {
    strongSelf.qqchose etc...
    }
    }];

    Et, si l'on est tourmenté de la performance, le if (strongSelf) évitera toute chance d'executer le code qui serait inutile si strongSelf était nil.

  • Merci :) (je vais rester sur les macros, c'est du code legacy et les macros sont utilisées partout).


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