4

システムにシングルトンを入れたいのですが、呼び出し元が何らかの「sharedInstance」メソッドを介してそれにアクセスするのではなく、シングルトンを使用していることに気付かないようにしたいのです。発信者が次のように言うことができるようにしたい:

MyClass *dontKnowItsASingleton = [[MyClass alloc] init];

これを実現するために、次のようにallocをオーバーライドしてみました。

// MyClass.m

static MyClass *_sharedInstance;

+ (id)alloc {

    if (!_sharedInstance) {
        _sharedInstance = [super alloc];
    }
    return _sharedInstance;
}

私の質問は:これは大丈夫ですか?動作しているようですが、これまでallocをオーバーライドしたことはありません。また、問題がなければ、これまで行ってきたdispatch_onceアプローチではなく、常にこの手法を使用できますか?..。

+ (id)sharedInstance {

    static SnappyTV *_sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[self alloc] init];
    });
    return _sharedInstance;
}
4

3 に答える 3

5

@ H2CO3で述べたように、シングルトンを生成する方法は受け入れられますが、スレッドセーフではありません。より伝統的なアプローチは、割り当てと比較を@synchronizedブロックにラップして、複数のスレッドへのアクセスを減らすことですが、オーバーライド+allocは、すでに不安定なパターンを実装するための最良の方法ではありません。

于 2012-12-22T21:02:03.523 に答える
1

initializeメソッドを利用する必要があると思います。

+ (void) initialize
{
    _sharedInstance= [[self alloc]init];
}


+ (id)sharedInstance 
{
    return _sharedIntsance;
}
于 2012-12-22T21:09:06.757 に答える
1

他の人が探しに来た場合に備えて、ここに私が思うすべての良いアドバイスを統合した解決策があります:

+ (id)alloc {

    @synchronized(self) {
        if (!_sharedInstance) {
            _sharedInstance = [super alloc];
        }
        return _sharedInstance;
    }
}

- (id)init {

    @synchronized(self) {
        static BOOL init = NO;
        if (!init) {
            init = YES;
            self = [super init];
        }
    }
    return self;
}

スレッドセーフの問題については@H2CO3、スレッドセーフの処方については@CodaFi、アークの下でのinitの危険性については@RobMayoffに感謝します。私は今日最高で最も明るい人に助けられました!

于 2012-12-22T22:40:13.783 に答える