Bearbeiten: Diese Implementierung ist mit ARC veraltet. Schauen Sie sich bitte an, wie ich einen Objective-C-Singleton implementiere, der mit ARC kompatibel ist. für die korrekte Umsetzung.
Alle Implementierungen von initialize, die ich in anderen Antworten gelesen habe, haben einen gemeinsamen Fehler.
+ (void) initialize {
_instance = [[MySingletonClass alloc] init] // <----- Wrong!
}
+ (void) initialize {
if (self == [MySingletonClass class]){ // <----- Correct!
_instance = [[MySingletonClass alloc] init]
}
}
In der Apple-Dokumentation wird empfohlen, den Klassentyp in Ihrem Initialisierungsblock zu überprüfen. Weil Unterklassen standardmäßig die Initialisierung aufrufen. Es gibt einen nicht offensichtlichen Fall, in dem Unterklassen indirekt über KVO erstellt werden können. Wenn Sie die folgende Zeile in eine andere Klasse einfügen:
[[MySingletonClass getInstance] addObserver:self forKeyPath:@"foo" options:0 context:nil]
Objective-C erstellt implizit eine Unterklasse von MySingletonClass, was zu einer zweiten Auslösung von führt +initialize
.
Möglicherweise sollten Sie implizit prüfen, ob Ihr Init-Block als solcher doppelt initialisiert ist:
- (id) init { <----- Wrong!
if (_instance != nil) {
// Some hack
}
else {
// Do stuff
}
return self;
}
Aber du wirst dich in den Fuß schießen; oder schlimmer noch, geben Sie einem anderen Entwickler die Möglichkeit, sich in den Fuß zu schießen.
- (id) init { <----- Correct!
NSAssert(_instance == nil, @"Duplication initialization of singleton");
self = [super init];
if (self){
// Do stuff
}
return self;
}
TL; DR, hier ist meine Implementierung
@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
(Ersetzen Sie ZAssert durch unser eigenes Assertionsmakro oder nur durch NSAssert.)