Düzenleme: Bu uygulama ARC ile eski. Lütfen bir göz atın ARC ile uyumlu bir Objective-C singletonunu nasıl uygularım? doğru uygulama için.
Diğer cevaplarda okuduğum başlatmanın tüm uygulamaları ortak bir hatayı paylaşır.
+ (void) initialize {
_instance = [[MySingletonClass alloc] init] // <----- Wrong!
}
+ (void) initialize {
if (self == [MySingletonClass class]){ // <----- Correct!
_instance = [[MySingletonClass alloc] init]
}
}
Apple belgeleri, başlatma bloğunuzdaki sınıf türünü kontrol etmenizi önerir. Çünkü alt sınıflar varsayılan olarak başlatmayı çağırır. Alt sınıfların dolaylı olarak KVO aracılığıyla oluşturulabileceği açık olmayan bir durum vardır. Başka bir sınıfa aşağıdaki satırı eklerseniz:
[[MySingletonClass getInstance] addObserver:self forKeyPath:@"foo" options:0 context:nil]
Objective-C dolaylı olarak MySingletonClass alt sınıfını oluşturacak ve bunun ikinci bir tetiklenmesine neden olacaktır +initialize
.
İnit bloğunuzda yinelenen başlatmayı dolaylı olarak kontrol etmeniz gerektiğini düşünebilirsiniz:
- (id) init { <----- Wrong!
if (_instance != nil) {
// Some hack
}
else {
// Do stuff
}
return self;
}
Ama kendini ayağından vuracaksın; ya da daha kötüsü, başka bir geliştiriciye kendilerini ayağa vurma fırsatı verin.
- (id) init { <----- Correct!
NSAssert(_instance == nil, @"Duplication initialization of singleton");
self = [super init];
if (self){
// Do stuff
}
return self;
}
TL; DR, işte benim uygulamam
@implementation MySingletonClass
static MySingletonClass * _instance;
+ (void) initialize {
if (self == [MySingletonClass class]){
_instance = [[MySingletonClass alloc] init];
}
}
- (id) init {
ZAssert (_instance == nil, @"Duplication initialization of singleton");
self = [super init];
if (self) {
// Initialization
}
return self;
}
+ (id) getInstance {
return _instance;
}
@end
(ZAssert'i kendi iddia makamımızla değiştirin veya yalnızca NSAssert'i kullanın.)