Bearbeiten: Diese Implementierung ist mit ARC überholt. Bitte werfen Sie einen Blick auf Wie kann ich ein Objective-C-Singleton implementieren, das mit ARC kompatibel ist? für eine korrekte Umsetzung.
Alle Implementierungen von initialize, die ich in anderen Antworten gelesen habe, weisen einen gemeinsamen Fehler auf.
+ (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. Denn Unterklassen rufen das Initialize standardmäßig auf. Es gibt einen nicht offensichtlichen Fall, in dem Unterklassen indirekt durch KVO erstellt werden können. Wenn Sie nämlich die folgende Zeile in einer anderen Klasse hinzufügen:
[[MySingletonClass getInstance] addObserver:self forKeyPath:@"foo" options:0 context:nil]
Objective-C wird implizit eine Unterklasse von MySingletonClass erstellen, was zu einer zweiten Auslösung von +initialize
.
Sie denken vielleicht, dass Sie in Ihrem init-Block implizit auf doppelte Initialisierung prüfen sollten:
- (id) init { <----- Wrong!
if (_instance != nil) {
// Some hack
}
else {
// Do stuff
}
return self;
}
Aber Sie werden sich selbst in den Fuß schießen; oder schlimmer noch, einem anderen Entwickler die Gelegenheit geben, sich selbst 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 Umsetzung
@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 Assertion-Makro; oder einfach NSAssert).