編集:この実装はARCで廃止されました。ARCと互換性のあるObjective-Cシングルトンの実装方法をご覧ください。正しい実装のために。
他の回答で読んだすべての初期化の実装には、共通のエラーがあります。
+ (void) initialize {
_instance = [[MySingletonClass alloc] init] // <----- Wrong!
}
+ (void) initialize {
if (self == [MySingletonClass class]){ // <----- Correct!
_instance = [[MySingletonClass alloc] init]
}
}
Appleのドキュメントでは、initializeブロックのクラスタイプを確認することをお勧めしています。サブクラスはデフォルトで初期化を呼び出すためです。サブクラスが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に置き換えます。)