編集:この実装はARCで廃止されました。ARCと互換性のあるObjective-Cシングルトンを実装するにはどうすればよいですか?をご覧ください。正しく実装するため。
私が他の回答で読んだ初期化のすべての実装は、共通のエラーを共有しています。
+ (void) initialize {
_instance = [[MySingletonClass alloc] init] // <----- Wrong!
}
+ (void) initialize {
if (self == [MySingletonClass class]){ // <----- Correct!
_instance = [[MySingletonClass alloc] init]
}
}
Appleのドキュメントでは、初期化ブロックのクラスタイプを確認することを推奨しています。サブクラスはデフォルトで初期化を呼び出すためです。サブクラスがKVOを介して間接的に作成される可能性があるという非自明なケースが存在します。別のクラスに次の行を追加した場合:
[[MySingletonClass getInstance] addObserver:self forKeyPath:@"foo" options:0 context:nil]
Objective-Cは、MySingletonClassのサブクラスを暗黙的に作成し、その結果、の2番目のトリガーが発生し+initialize
ます。
initブロックの初期化が重複していないか暗黙的にチェックする必要があると思うかもしれません。
- (id) init { <----- Wrong!
if (_instance != nil) {
// Some hack
}
else {
// Do stuff
}
return self;
}
しかし、あなたは自分の足を撃ちます。さらに悪いことに、別の開発者に自分の足を撃つ機会を与えます。
- (id) init { <----- Correct!
NSAssert(_instance == nil, @"Duplication initialization of singleton");
self = [super init];
if (self){
// Do stuff
}
return self;
}
TL; DR、これが私の実装です
@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を独自のアサーションマクロ、または単にNSAssertに置き換えます。)