Sunting: Implementasi ini usang dengan ARC. Silakan lihat Bagaimana cara mengimplementasikan singleton Objective-C yang kompatibel dengan ARC? untuk implementasi yang benar.
Semua implementasi inisialisasi yang saya baca di jawaban lain berbagi kesalahan umum.
+ (void) initialize {
_instance = [[MySingletonClass alloc] init] // <----- Wrong!
}
+ (void) initialize {
if (self == [MySingletonClass class]){ // <----- Correct!
_instance = [[MySingletonClass alloc] init]
}
}
Dokumentasi Apple merekomendasikan Anda memeriksa jenis kelas di blok inisialisasi Anda. Karena subclass memanggil inisialisasi secara default. Ada kasus yang tidak jelas di mana subclass dapat dibuat secara tidak langsung melalui KVO. Karena jika Anda menambahkan baris berikut di kelas lain:
[[MySingletonClass getInstance] addObserver:self forKeyPath:@"foo" options:0 context:nil]
Objective-C secara implisit akan membuat subkelas MySingletonClass yang menghasilkan pemicu kedua +initialize
.
Anda mungkin berpikir bahwa Anda harus secara implisit memeriksa inisialisasi duplikat di blok init Anda seperti itu:
- (id) init { <----- Wrong!
if (_instance != nil) {
// Some hack
}
else {
// Do stuff
}
return self;
}
Tapi Anda akan menembak diri sendiri di kaki; atau lebih buruk memberi pengembang lain kesempatan untuk menembak diri mereka sendiri.
- (id) init { <----- Correct!
NSAssert(_instance == nil, @"Duplication initialization of singleton");
self = [super init];
if (self){
// Do stuff
}
return self;
}
TL; DR, ini implementasi saya
@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
(Ganti ZAssert dengan makro pernyataan kami sendiri; atau hanya NSAssert.)