Le point sur ARC

13»

Réponses

  • CéroceCéroce Membre, Modérateur
    octobre 2012 modifié #62
    Bon en gros, c'est simple:

    - avec ARC, on ne peut plus créer un vrai Singleton, c'est à  dire être sûr qu'il n'existera qu'une seule instance, parce qu'on ne peut plus surcharger les méthodes +alloc et -release.

    - on utilise donc le pattern "Shared Instance" qui offre le même bénéfice que le Singleton: avoir un seul objet pour toute l'appli.
  • AliGatorAliGator Membre, Modérateur
    'Ceetix' a écrit:
    Ali, j'ai lu ton post sur le singleton 2.0 et je suis bien d'accord avec l'évolution que tu donnes à  cette structure mais dans ton exemple, comme fais-tu pour récupérer une instance qui t'intéresse ?
    Bah heu pour ça tu fais... comme pour une classe non-singleton.

    La seule différence maintenant entre une classe normale et une classe qui utilise ce pattern "Shared Instance" c'est juste cette méthode +sharedInstance qui permet d'accéder à  une instance donnée depuis toute l'appli. Mais sans ça, le reste c'est pareil. Donc tu fais comme tu veux. Tu peux avoir besoin dans un ViewController particulier d'un TVService qui va pointer sur sa propre baseURL ou avoir sa propre configuration différente de celle de la sharedInstance, du coup tu créeras une instance de TVService que tu stockeras dans une @property, comme tu fais d'habitude. Comme pour n'importe quel autre objet quoi.



    Regarde la classe NSFileManager d'Apple : cette classe a bien une méthode +defaultManager d'un côté, qui te donne accès à  une instance toujours accessible de partout dans ton appli, mais elle te permet également de faire un alloc/init d'une instance indépendante, et tu peut tout à  fait l'utiliser comme telle. Bah c'est pareil.



    Après si tu as besoin d'avoir accès à  plusieurs objets TVService partout dans ton appli, avec des baseURL différentes, ce ne sont plus vraiment chacune des instances ponctuelles que tu crées à  la demande, ce n'est plus non plus une seule et unique sharedInstance, c'est plutôt en effet par exemple un dictionnaire d'instances, et non plus une méthode +sharedInstance que tu vas écrire mais une méthode +instanceWithBaseURL par exemple :
    +(instancetype)instanceWithBaseURL:(NSURL*)baseURL<br />
    {<br />
        static NSMutableDictionary* instances;<br />
        static dispatch_once_t once;<br />
        dispatch_once(&amp;once, ^{ instances = [[NSMutableDictionary alloc] init]; });<br />
        TVService* inst = [instances objectForKey:baseURL];<br />
        if (&#33;inst) {<br />
            inst = [[[TVService alloc] initWithBaseURL:baseURL] autorelease];<br />
            [instances setObject:inst forKey:baseURL];<br />
        }<br />
        return inst;<br />
    }
    Enfin un truc dans le style quoi. A toi d'adapter à  tes besoins
  • AliGatorAliGator Membre, Modérateur
    'muqaddar' a écrit:


    Sinon, juste pour info, voilà  comment j'écris mon singleton sans ARC:
    Mmmmh je vais pas rentrer dans les détails, mais ton code n'est pas sans quelques étrangetées.
    • Déjà  ce n'est pas lazy-loaded. C'est dommage.
    • Je vois pas l'intérêt de créer ton instance dans le +initialize si tôt, même si tu n'as jamais besoin de ton instance dans ton appli. En plus, tu ne fais pas de vérification de classe dans initialize comme on est sensé faire quand on surcharge cette méthode, donc ça ne marchera plus si tu sous-classes un jour ta classe.
    • Ce n'est pas thread-safe
    • Ca ne garantit pas que ta sharedInstance ne soit pas deallocated (ce qui te mènerai à  un joli EXC_BADACCESS). Pour éviter ça l'implémentation que propose Apple surcharge retain et release mais aussi retainCount pour lui donner une valeur magique indiquant un objet ne pouvant pas être déalloué (INT_MAX, je crois, de mémoire), ce que tu ne fais pas
    • Du coup tes tests dans allocWithZone et init n'ont plus trop de sens (en plus, allocWithZone n'est plus utilisé depuis des lustres, il ne reste présent que par pur historique mais Apple n'utilise plus les NSZones)


    Si tu as une implémentation de singleton à  écrire sans ARC, celle avec GCD reste en général mieux, plus concise et suffisante, même si c'est qu'une sharedInstance et pas un vrai singleton, et si tu veux un vrai singleton, je te conseille plutôt l'implémentation proposée par Apple dans sa doc.
  • AliGatorAliGator Membre, Modérateur
    'Céroce' a écrit:


    Bon en gros, c'est simple:

    - avec ARC, on ne peut plus créer un vrai Singleton, c'est à  dire être sûr qu'il n'existera qu'une seule instance, parce qu'on ne peut plus surcharger les méthodes +alloc et -release.

    - on utilise donc le pattern "Shared Instance" qui offre le même bénéfice que le Singleton: avoir un seul objet pour toute l'appli.
    Oui c'est tout à  fait ça.



    Ceci dit j'ai jamais creusé, mais si on voulais vraiment un singleton (= interdire la création de nouvelles instances) je me demande si on ne pourrait pas le faire même avec ARC, en surchargeant init pour que ça fasse release self et retourne la sharedInstance à  la place ? Bon j'ai pas testé ni réfléchi + que ça au problème, mais ça donnerait un truc comme ça :
    -(id)init<br />
    {<br />
      if (&#33;sharedInstance)<br />
      {<br />
        self = [super init];<br />
        sharedInstance = self;<br />
      } else {<br />
    #if &#33; __has_feature(objc_arc)<br />
        [self release];<br />
    #endif<br />
        self = sharedInstance;<br />
      }<br />
      return self;<br />
    }<br />
    #if &#33; __has_feature(objc_arc)<br />
    -(id)release { return self; }<br />
    #endif<br />
    Comme ça chaque paire alloc+init finirait pas retourner la sharedInstance. Et si on est en MRC, si on tente de faire un release ça ne risquera pas de désallouer la sharedInstance avec la surcharge de la méthode release. Il y a certainement d'autres subtilités à  rajouter pour que ça marche dans tous les cas, j'y ai pas vraiment réfléchi, mais je me dis que c'est peut-être jouable quand même du coup ?



    Mais bon, ceci dit, franchement je ne vois pas l'intérêt. Je ne trouve aucun exemple concret d'une raison pour laquelle on voudrait à  tout prix interdire la création d'autres instances que la sharedInstance. Qu'on veuille une sharedInstance commune accessible de partout, oui, c'est assez commun. Qu'on ne veuille pas qu'il y ait d'autres instances que cette sharedInstance, en général c'est une contrainte qui n'a pas de raison d'être. Donc pourquoi se prendre la tête à  tenter de l'implémenter...?
  • CéroceCéroce Membre, Modérateur
    'AliGator' a écrit:


    Je ne trouve aucun exemple concret d'une raison pour laquelle on voudrait à  tout prix interdire la création d'autres instances que la sharedInstance.


    J'imagine que quand on travaille en équipe ça peut présenter un intérêt si le collègue a survolé le .h un peu vite.



    De toute façon, on pourrait discuter pendant des heures de l'intérêt même du Singleton, sur l'utilisation duquel le Gang of Four émettait déjà  des réserve en 1995. C'est très bien les design patterns, mais comme tout outil, il faut connaà®tre leurs limites.
  • muqaddarmuqaddar Administrateur
    C'est vrai que Renaud, tu es un peu anti-singleton ! image/smile.png' class='bbc_emoticon' alt=':)' />
  • AliGatorAliGator Membre, Modérateur
    Moi aussi je suis anti-singleton. Je suis pro-sharedInstance, mais uniquement, et vraiment uniquement, quand ça a du sens de l'utiliser. Mon utilisation typique de ce pattern sharedInstance est pour l'implémentation d'une interface Objective-C pour aller interroger un WebService. Je suis pas sûr de l'avoir utilisé dans beaucoup d'autres contextes en fait.
  • 'AliGator' a écrit:


    Moi aussi je suis anti-singleton. Je suis pro-sharedInstance, mais uniquement, et vraiment uniquement, quand ça a du sens de l'utiliser. Mon utilisation typique de ce pattern sharedInstance est pour l'implémentation d'une interface Objective-C pour aller interroger un WebService. Je suis pas sûr de l'avoir utilisé dans beaucoup d'autres contextes en fait.




    Interrogation de WS ou de manière générale pour l'accès aux données (encapsulation de CoreData, accès au WS, gestion du cache...)
  • AliGatorAliGator Membre, Modérateur
    Ah oui en effet pour ça aussi image/wink.png' class='bbc_emoticon' alt=';)' />
  • les préférences...
  • muqaddarmuqaddar Administrateur
    'xyloweb' a écrit:


    les préférences...




    Développe ! C'est un peu court.
  • AliGatorAliGator Membre, Modérateur
    Pour les préférences il y a déjà  un singleton/sharedInstance qui existe dans le SDK (NSUserDefaults), pourquoi vouloir en créer un nous mêmes ? (ou peut-être pour avoir une API spécifique pour notre application plutôt que de passer par des clés/valeurs ?)



    (En effet un peu light ton message pas très explcite du coup...)
  • muqaddarmuqaddar Administrateur
    Je pense qu'il parlait plutôt des goûts et des couleurs... donc au sens figuré.
  • AliGatorAliGator Membre, Modérateur
    'muqaddar' a écrit:
    Je pense qu'il parlait plutôt des goûts et des couleurs... donc au sens figuré.
    Ah, si c'est dans ce sens là  en effet (et c'est vrai que les points de suspension peuvent le laisser penser) c'est encore plus évasif comme réponse. Et moins adapté du coup, car les Design Patterns, c'est pas qu'une question de feeling, au contraire le principe même d'avoir des DP c'est que leurs usages et études de cas a déjà  été éprouvé...
  • Je voulais parler du DP singleton pour accéder aux préférences d'une appli.



    bon de toute façon, pour ma part (et jusqu'à  nouvel ordre) j'abandonne le mode ARC (et le storyboard, d'ailleurs au passage)

    je me trompe peut être, et comme tout choix il est critiquable mais bon, j'assume ;-)



    trop casse gueule et pas assez lisible. j'aime bien maà®triser les choses... c'est plus rassurant.
  • AliGatorAliGator Membre, Modérateur
    ARC ou non ça ne change pas le fait que l'implémentation GCD a bien plus d'avantages que sa contrepartie obsolète de surcharger les retain/release/allocWithZone/retainCount et tout le tintouin. Après perso moi aussi j'aime bien maà®triser et pour l'instant j'utilise encore beaucoup MRC, mais ça ne m'empêche pas de préférer l'implémentation GCD pour ce DP.



    D'autant que les remarques plus haut sur les contraintes inutiles quant à  l'interdiction de créer plusieurs instances restent d'actualité, et qu'en général on a juste besoin, un peu comme NSFileManager, que d'une instance partagée, mais sans avoir la contrainte d'empêcher la création d'autres instances. Et que GCD apporte plusieurs avantages avec son approche, déjà  évoqués plus haut.
  • BooleanneBooleanne Membre
    novembre 2012 modifié #78
    Personnellement, débutante depuis le début de cette année, j'ai choisi d'utiliser ARC. Je ne suis pas assez experte pour vous dire si c'est satisfaisant par rapport à  la gestion mémoire ou pas, mais il semble que je n'ai pas de leak.



    On est quand-même obligé de comprendre la gestion mémoire, si on alloue en local ou pas, etc. Et puis, il y a toujours la possibilité de mettre des objets à  nil en cas de doute.

    Le ménage se fait bien malgré tout car en cas d'erreur on se retrouve avec un objet inexistant.

    Comme je n'ai pas connu les alloc-dealloc, je n'ai pas eu à  faire la transition, et je pense que cela a allégé mon initiation.



    Je n'ai ni assez d'expérience, ni assez de recul, mais à  priori, cela me satisfait, pour le moment.
Connectez-vous ou Inscrivez-vous pour répondre.