Méthodes d'instances pour un singleton

Bonjour !


 


Je me rends compte que dans les singletons (en fait shared instances) que je crée, je ne mets en public interface pratiquement que des méthodes de classes !


 


Par exemple :



@interface MyCBDPurchasingManager : NSObject

+ (instancetype)purchasingManager ;

+ (BOOL)isPurchased:(MyObject *)myObject ;

@end

Ensuite, quand j'implémente ces méthodes, bien souvent j'ai en interne une méthode d'instance que j'appelle sur la shared instance.



@implementation MyCBDPurchasingManager


- (instancetype)init
{
self = [super init] ;

if (self)
{
_purchasedObjects = [NSMutableDictionary new] ;
}

return self ;
}



+ (instancetype)purchasingManager
{
static id _sharedInstance = nil ;
static dispatch_once_t onceToken;

dispatch_once(&onceToken,
^{
_sharedInstance = [[self alloc] init];
});

return _sharedInstance;
}




+ (BOOL)isPurchased:(MyObject *)obj
{
return [[self purchasingManager] isPurchased:obj];
}


- (BOOL)isPurchased:(MyObject *)obj
{
return [self.purchasedObjects[obj.id] boolValue] ;
}

@end

Est-ce que c'est une bonne pratique ? Est-ce ça change rien ?


 


Merci !


 


Colas


Réponses

  • Salut,


     


    Je pense que c'est une bonne pratique. Tu peux même mettre la méthode purchasingManager en private ( dans l'extension de la classe) si tu as juste des méthodes de classe en public. 


     


    PS : Je ne sais pas si ton message est dans la bonne section ? :)


  • AliGatorAliGator Membre, Modérateur
    février 2015 modifié #3
    Oui je fais pareil.


    Il existe une solution alternative qui est de mettre à  profit la méthode "+[NSObject forwardingTargetForSelector]" pour que tout message inconnu / non implémenté envoyé à  ta classe soit forwardé à  la sharedInstance.


    Sauf qu'en pratique c'est nul car tu n'as plus d'aitocompletion, ainsi que des warnings partout concernant des méthodes que tu appelles qui n'existent pas d'après le ".h"... donc au final c'est aussi simple de faire comme tu fais.
  • @samir


    Effectivement, on n'a même plus besoin de savoir que c'est une sharedInstance !
  • AliGatorAliGator Membre, Modérateur
    L'autre méthode sinon c'est de ne pas faire de méthode d'instance du tout et implémenter ton code directement dans les méthodes de classe.


    Et du coup quand tu as besoin d'accéder à  des propriétés tu fais "self.purchasingManager.purchasedObjects" dans ta méthode "+ isPurchased" au lieu de faire "self.purchasedObjects" dans ta méthode "- isPurchased".
  • CéroceCéroce Membre, Modérateur

    Franchement, il faut surtout arrêter avec les singletons à  toutes les sauces. Qu'est-ce qui t'empêche d'instancier cet objet ? C'est pas comme si ça servait dans toute l'appli.


  • FKDEVFKDEV Membre
    février 2015 modifié #7

    A part rendre le code moins lisible, je ne vois pas trop l'interet.


    Quitte à  ecrire des methodes statiques pour taper dans un objet global, autant mettre tes donnees en static dans le fichier .m.  >:D 

     



    static NSMutableArray *purchasedObjects;

    @implementation MonCodeEnVrac

    + (BOOL)isPurchased:(MyObject *)obj
    {
    return [purchasedObjects[obj.id] boolValue] ;
    }
    @end

  • AliGatorAliGator Membre, Modérateur
    février 2015 modifié #8

    Ouais, et briser la garantie d'atomicité d'accès...  >:)


     


    Tu vas me dire, la garantie d'atomicité d'accès d'une propriété ne garantit pas l'atomicité de tout le système, donc dans tous les cas il faut faire gaffe à  ce genre de choses (cf l'excellente présentation de Andy Matuschak à  Realm qui circule récemment sur Twitter) mais n'empêche...


  • FKDEVFKDEV Membre
    février 2015 modifié #9
  • AliGatorAliGator Membre, Modérateur
    Le truc pas optimisé et que plus personne n'utilise ? ^^ passe à  GCD... (ou à  des locks POSIX à  la limite)


    De ce côté Swift va quand même pas mal changer la donne en tout cas :

    - la plupart des cas où on fait une classe ne contenant que des méthodes de classe c'est pour avoir une certaine forme de namespace pour grouper les méthodes ensemble. Or contrairement à  ObjC, Swift a déjà  ce concept de namespace.

    - le besoin d'un singleton en ObjC est aussi souvent à  cause du manque de concept de variable de classe en ObjC. Swift 1.2 supporte les variables de classe et de struct.

    - Pour le côté atomicité, l'utilisation des ValueTypes (utiliser struct plutôt que class typiquement) garantit que chaque ValueTypes n'a qu'un seul owner et que chaque instance est passée par copie. ça ne résoud pas tous les cas où l'atomicité est garantie mais ça évite pas mal de cas où elle est autrement nécessaire en ObjC.
Connectez-vous ou Inscrivez-vous pour répondre.