2013-07-23 15 views

Odpowiedz

12

Apple zaleca ścisłe singleton realizacji (brak innych żywych obiektów tego samego typu jest dozwolone) w ten sposób:

+ (instancetype)singleton { 
    static id singletonInstance = nil; 
    if (!singletonInstance) { 
     static dispatch_once_t onceToken; 
     dispatch_once(&onceToken, ^{ 
      singletonInstance = [[super allocWithZone:NULL] init]; 
     }); 
    } 
    return singletonInstance; 
} 

+ (id)allocWithZone:(NSZone *)zone { 
    return [self singleton]; 
} 

- (id)copyWithZone:(NSZone *)zone { 
    return self; 
} 

Link do jabłka documentation (bottom of page, Without ARC)

+0

już robisz dispatch_once(), czy trzeba to zrobić, jeśli (! SingletonInstance)? Wierzę, że dispatch_once() obsłuży to dla nas na podstawie innych rzeczy, takich jak synchronizacja. – pnizzle

+0

@pnizzle masz rację, dispatch_once wystarczy, sprawdzanie instancji wcześniej może być szybsze. –

+0

Czy "allocWithZith:' przestarzałe? Wygląda na to, gdy próbuję to zaimplementować. – Fogh

0

Podniosłem ten przykładowy kod z bloga duckrowing: http://www.duckrowing.com/2011/11/09/using-the-singleton-pattern-in-objective-c-part-2/

W ncurses.h mamy

@interface Foo : NSObject 
+ (Foo *) sharedFoo; 
@end 

aw .m mamy

static SLFoo *sharedInstance = nil; 
static dispatch_queue_t serialQueue; 

@implementation Foo 

- (id)init 
{ 
    id __block obj; 

    dispatch_sync(serialQueue, ^{ 
     obj = [super init]; 
     if (obj) { 
      ; 
     } 
    }); 

    self = obj; 
    return self; 
} 

+ (Foo *) sharedFoo; 
{ 
    static dispatch_once_t onceQueue; 

    dispatch_once(&onceQueue, ^{ 
     if (sharedInstance) { 
      return; 
     } 
     sharedInstance = [[Foo alloc]init]; 
    }); 
    return sharedInstance; 

} 

+ (id)allocWithZone:(NSZone *)zone 
{ 
    static dispatch_once_t onceQueue; 

    dispatch_once(&onceQueue, ^{ 
     serialQueue = dispatch_queue_create("com.mydomain.myApp.SerialQueueFoo", NULL); 
     if (sharedInstance == nil) { 
      sharedInstance = [super allocWithZone:zone]; 
     } 
    }); 

    return sharedInstance; 
} 

@end 

zauważy allocWithZone .

+0

Po pierwsze, zachowanie, które próbujesz zaimplementować, polega na tym, że [[alloc] init] powinien zwrócić dokładnie ten sam obiekt co + sharedFoo. Istnieją przypadki takie jak NSFileManager, gdzie istnieje wspólny singleton, ale [[alloc] init] zwraca inną instancję. W twoim przypadku, myślę, że możesz po prostu wstawić dispatch_once do init zamiast dispatch_sync i zapomnieć o allocWoneZone. – gnasher729

+0

W jaki sposób można uzyskać singleton z więcej niż jedną unikalną instancją? –

+0

NSFileManager dostarcza _singleton_, który może zrobić większość rzeczy, które chcesz zrobić. Dostarcza także pojedyncze instancje, które można modyfikować w bardziej złożonych sytuacjach. Tak więc sharedInstance jest singletonem, ale [[alloc] init] nie jest. – gnasher729

2

Może to być pomocne,

static Foo *sharedInstance = nil; 

+ (Foo *)sharedInstance { 

    if (sharedInstance == nil) { 

     sharedInstance = [[super allocWithZone:NULL] init]; 
    } 

    return sharedInstance; 
} 

+ (id)allocWithZone:(NSZone *)zone { 
    @synchronized(self) 
    { 
     if (sharedInstance == nil) { 
      sharedInstance = [super allocWithZone:zone]; 
      return sharedInstance; 
     } 
    } 
    return nil; 
} 
Powiązane problemy