346 votes

Créer singleton à l'aide d'un PGCD de dispatch_once en Objective-C

Si vous pouvez cibler iOS 4.0 ou supérieur

À l'aide de PGCD, est-il le meilleur moyen de créer un singleton en Objective-C (thread-safe)?

+ (instancetype)sharedInstance
{
    static dispatch_once_t once;
    static id sharedInstance;
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

217voto

Dave DeLong Points 156978

C'est parfaitement acceptable et thread-safe façon de créer une instance de votre classe. Il ne peut pas techniquement être un "singleton" (en ce sens qu'il ne peut jamais être de 1 de ces objets), mais aussi longtemps que vous utilisez uniquement l' [Foo sharedFoo] méthode pour accéder à l'objet, ce est assez bon.

36voto

Nietzsche Points 146

instancetype

type d'instance est juste l'une des nombreuses extensions de langage Objective-C, avec plus étant ajoutés à chaque nouvelle version.

Connaître, de l'aimer.

Et le prendre comme un exemple de la façon de payer l'attention sur les détails de bas niveau peut vous donner des aperçus nouveaux et puissants moyens de transformer Objective-C.

http://nshipster.com/instancetype/


+ (instancetype)sharedInstance
{
    static dispatch_once_t once;
    static id sharedInstance;

    dispatch_once(&once, ^
    {
        sharedInstance = [self new];
    });

    return sharedInstance;
}

+ (Class*)sharedInstance
{
    static dispatch_once_t once;
    static Class *sharedInstance;

    dispatch_once(&once, ^
    {
        sharedInstance = [self new];
    });

    return sharedInstance;
}

34voto

Spetruk Points 41

MySingleton.h

@interface MySingleton : NSObject

+(instancetype) sharedInstance;

+(instancetype) alloc __attribute__((unavailable("alloc not available, call sharedInstance instead")));
-(instancetype) init __attribute__((unavailable("init not available, call sharedInstance instead")));
+(instancetype) new __attribute__((unavailable("new not available, call sharedInstance instead")));
-(instancetype) copy __attribute__((unavailable("copy not available, call sharedInstance instead")));

@end

MySingleton.m

@implementation MySingleton

+(instancetype) sharedInstance {
    static dispatch_once_t pred;
    static id shared = nil;
    dispatch_once(&pred, ^{
        shared = [[super alloc] initUniqueInstance];
    });
    return shared;
}

-(instancetype) initUniqueInstance {
    return [super init];
}

@end

6voto

CanO Points 163

Vous pouvez éviter que la classe sera alloué à la réécriture de la méthode alloc.

@implementation MyClass

static BOOL useinside = NO;
static id _sharedObject = nil;


+(id) alloc {
    if (!useinside) {
        @throw [NSException exceptionWithName:@"Singleton Vialotaion" reason:@"You are violating the singleton class usage. Please call +sharedInstance method" userInfo:nil];
    }
    else {
        return [super alloc];
    }
}

+(id)sharedInstance
{
    static dispatch_once_t p = 0;
    dispatch_once(&p, ^{
        useinside = YES;
        _sharedObject = [[MyClass alloc] init];
        useinside = NO;
    });   
    // returns the same object each time
    return _sharedObject;
}

5voto

Christian Points 1630

Dave est correct, c'est parfait. Vous voudrez peut-être vérifier d'Apple docs sur la création d'un singleton pour des conseils sur la mise en œuvre de certaines autres méthodes pour s'assurer que seul peut jamais être créé que si les classes de choisir de ne PAS utiliser le sharedFoo méthode.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X