まあ、init
の簡単な方法は、デフォルトNSObject実装(これはself
を返す)を呼び出さないようにすることです。次に、sharedInstance
関数の場合、シングルトンをインスタンス化するときにinitのような作業を実行するプライベート関数を定義して呼び出します。 (これにより、ユーザーは誤ってシングルトンを再初期化することはありません)。
ただし、大きな問題は、alloc
があなたのコードのユーザによって呼び出されていることです!このために、私は個人的にallocWithZone:
をオーバーライドするAppleのルートをお勧めします...
+ (id)allocWithZone:(NSZone *)zone
{
return [[self sharedInstance] retain];
}
これは、ユーザーがまだあなたのシングルトンインスタンスを取得します、そして、彼らはそれを割り当てられたかのように、彼らは誤って使用することができ、かつ安全このため、一度それを解放意味しますカスタムallocはシングルトンにretainを実行します。 (注:alloc
はallocWithZone:
となり、別々に上書きする必要はありません)
私はあなたがより多くの情報が必要な場合は知ってみましょう〜
EDIT:例と詳細を提供するために、答えを拡大 - 、それはだ
を考慮にCatfish_Manの答えを撮影しばしば、防弾シングルトンを作成することが重要ではないと代わりにヘッダ/ドキュメントに分かりやすいコメントを書いてassert
に入れてください。
私の場合、スレッドセーフな遅延ロードシングルトンが必要でした。つまり、アプリケーションの起動時に自動的に割り当てられる代わりに、使用するまで割り当てられません。それをどうやって安全に行うのかを学んだ後、私はそれをもっていっぱい行くかもしれないと思った。
EDIT#2:私は現在、アプリケーションの存続期間中にシングルトンオブジェクトを1回だけ割り当てるスレッドセーフな方法として、GCDのdispatch_once(...)
を使用します。 Apple Docs: GCD dispatch_onceを参照してください。
//Hidden/Private initialization
-(void)singletonInit
{
//your init code goes here
}
static HSCloudManager * sharedInstance = nil;
+ (HSCloudManager *) sharedManager {
static dispatch_once_t dispatchOncePredicate = 0;
dispatch_once(&dispatchOncePredicate, ^{
sharedInstance = [[super allocWithZone:NULL] init];
[sharedInstance singletonInit];//Only place you should call singletonInit
});
return sharedInstance;
}
+ (id) allocWithZone:(NSZone *)zone {
//If coder misunderstands this is a singleton, behave properly with
// ref count +1 on alloc anyway, and still return singleton!
return [[HSCloudManager sharedManager] retain];
}
HSCloudManager
サブクラスNSObject
を、そして唯一のデフォルトを残しinit
を上書きしません。また、私はまだ誤って複数回呼び出されてからそれを防ぐためにsingletonInit
という名前Appleの古いシングルトンの例からallocWithZone:
オーバーライドビットを追加し、民間のinitを追加しましたNSObject
に実装されています.Appleのドキュメントによれば、それは自己を返すだけです。これは[[HSCloudManager alloc] init]
が[[[HSCloud Manager sharedManager] retain] self]
と同じであることを意味し、混乱したユーザーとマルチスレッドアプリケーションの両方を遅延ロードシングルトンとして安全にします。
あなたのシングルトンをサブクラス化することについて懸念していますが、私はちょうどコメント/明確にそれを文書化すると言うでしょう。盲目的にクラスを読み上げることなくサブクラス化する人は誰でもです。痛みのためにを求めています!
EDIT#3:ARC互換について、ちょうどallocWithZone:
オーバーライドから保持部分を除去するが、上書きを保ちます。
@yAaak、十分な公正と思われますしかし、私は無限ループのように感じ、それを消化する必要があります;)プライベートメソッドによるこのようなシングルトンの作成プロセスがスレッドセーフであることを保証するにはどうすればよいですか?その他の問題:Appleの 'allocWithZone'のアイデアに従えば、デフォルトのNSObjectの' init'が呼び出されます(単に 'self'を返すかsth else?)...そして、ユーザーが' alloc'と ' init'は私のプロパティ/ ivarsの初期化と 'init'をもう一度取得するNSObjectについて何か変更しますか? – matm
yAak、あなたは正しい:まあまあのアプローチは、今のところ十分なことを示唆している。あなたのコードを使ってシングルトンをもう少し試してみましょう:)あなたの答えはかなり広範で、Catfish_manの反対意見を取り入れているので、私はそれを受け入れています。再度、感謝します! – matm
OSAtomic *ではなくdispatch_once()をお勧めします。より速く、より速く、より厄介ではありません。 –