Corriger le Pattern Singleton Objective-C (iOS)?
J'ai trouvé quelques informations sur le net pour créer une classe singleton à l'aide de PGCD. C'est cool parce que c'est thread-safe avec de très faible hauteur. Malheureusement je ne pouvais pas trouver de solutions complètes, mais seulement des extraits de l'sharedInstance méthode. J'ai donc fait ma propre classe à l'aide de la méthode essai-erreur - et et voila - ce qui suit est sorti:
@implementation MySingleton
//MARK: -
//MARK: Singleton Pattern using GCD
+ (id)allocWithZone:(NSZone *)zone { return [[self sharedInstance] retain]; }
- (id)copyWithZone:(NSZone *)zone { return self; }
- (id)autorelease { return self; }
- (oneway void)release { /* Singletons can't be released */ }
- (void)dealloc { [super dealloc]; /* should never be called */ }
- (id)retain { return self; }
- (NSUInteger)retainCount { return NSUIntegerMax; /* That's soooo non-zero */ }
+ (MySingleton *)sharedInstance
{
static MySingleton * instance = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
//--- call to super avoids a deadlock with the above allocWithZone
instance = [[super allocWithZone:nil] init];
});
return instance;
}
//MARK: -
//MARK: Initialization
- (id)init
{
self = [super init];
if (self)
{
//Initialization code here.
}
return self;
}
@end
N'hésitez pas à commenter et me dire si j'ai raté quelque chose ou de faire quelque chose de complètement faux 😉
Cheers
Stefan
- Je serais tenté d'ajouter un
-(void)dealloc
qui lève une exception, de cette façon, vous devriez être en mesure de traquer la délinquance acteur si quelqu'un est d'obtenir une instance du singleton et puis en le relâchant. En plus d'être un abus du motif, je veux vous laisser avec un bancales pointeur. - meta question: est-ce que ce sera à [codereview.stackexchange.com/]?
- apple conseille fortement de ne pas créer des singletons primordial de conserver/release! cela permettra de briser les applications de la transition à l'ARC
- Double/étroitement liés: Quel est votre Objectif-C singleton ressembler?
Vous devez vous connecter pour publier un commentaire.
Faire simple:
Qui est-il. Primordial
retain
,release
,retainCount
et le reste est juste la clandestinité de bugs et l'ajout d'un tas de lignes de code inutile. Chaque ligne de code est un bug en attente de se produire. En réalité, si vous en êtes la causedealloc
d'être appelé sur votre instance partagée, vous avez un très sérieux bogue dans votre application. Ce bug devrait être corrigé, et non pas caché.Cette approche se prête également à la refactorisation à l'appui de la non-singleton utilisation de modes. À peu près chaque singleton qui survit au-delà de quelques releases sera finalement refait dans une situation de non-singleton forme. Certains (comme
NSFileManager
) continuer à soutenir un singleton mode tout en soutenant l'arbitraire de l'instanciation.Remarque que ci-dessus aussi "fonctionne" dans l'ARC.
release
le singleton. Parce qu'il est peu probable que le singleton de destruction n'a jamais été testé, la mise en œuvre de ladealloc
comme le montre est purement défensive mesure de rappeler à l'avenir vous avez passé, vous n'avez pas pensé à propos de la gestion de la mémoire pour cette classe.[[self class] alloc]
au lieu de[self alloc]
dans+
méthode?Être conscient que dispatch_once n'est pas réentrant, afin de l'appelant lui-même de l'intérieur de la dispatch_once bloc de blocage du programme.
N'essayez pas de code défensivement contre vous-même. Si vous n'êtes pas le codage d'un cadre, de traiter votre classe normale puis coller le singleton idiome ci-dessus. Pensez à le singleton idiome comme une méthode de convenance, non pas comme une caractéristique de votre classe. Vous voulez traiter votre classe comme une classe normale au cours de tests unitaires, donc c'est OK pour laisser accessible constructeur.
Ne vous embêtez pas à l'aide de
allocWithZone:
alloc
. Les zones mémoire sont plus utilisés en Objective-C, afin deallocWithZone:
ne sont conservés que pour la compatibilité avec l'ancien code.NSAllocateObject()
etclass_createInstance()
.Un singleton, factory méthode renvoie toujours l'un de ces trois types:
id
pour indiquer le type de retour n'est pas entièrement connue (cas où vous êtes la construction d'une classe de cluster).instancetype
pour indiquer que le type retourné est une instance de la classe englobante.MySingleton
dans l'exemple) pour garder les choses simples.Puisque vous tagged cet iOS, une alternative à un singleton est une économie de la ivar pour le délégué d'application, puis à l'aide d'une commodité de macro que vous pouvez redéfinir si vous changez d'avis:
Si vous voulez de l'unité de test de votre singleton, vous devez également faire en sorte que vous pouvez le remplacer par un simulacre de singleton et/ou de le remettre à la normale: