単例を使用する際に注意しなければならない問題

3278 ワード

今日、単一の例で発見された質問です.
単例の初期化の时、きっと単例に対する引用が现れません!!!
 
テストの例を書きました.
単一クラスSingletonClassとこの単一クラスで使用されるクラスSomeClass
@implementation SingletonClass



+ (id)sharedSingletonClass

{

    static SingletonClass* _singleton = nil;

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        _singleton = [[self alloc] init];

    });

    return _singleton;

}



- (id)init

{

    self = [super init];

    if (self)

    {

        self.number = 10;// 

        self.someClass = [[SomeClass alloc] init];// SomeClass

    }

    return self;

    

}



@end

SomeClass:
@implementation SomeClass



- (id)init

{

    self = [super init];

    if (self)

    {

        _number = [[SingletonClass sharedSingletonClass] number];// number 

    }

    return self;

}



@end

 
運転中に発見された
        NSLog(@"Hello, World!");

        

        NSLog(@"%@:", [SingletonClass sharedSingletonClass]);

        

        NSLog(@"Hello, World!");

2番目のhelloworldは永遠に実行できません
理由は簡単で、循環呼び出して、単例の初期化の過程の中で、また単例の初期化を呼び出して、そのため永遠にこの死の循環から飛び出しません
dispatch_でonceの単例と従来よく用いられていた単例生成方法はここでは区別されない.
ただの目視dispatch_onceは「dispatch_twice」を発見した後、静止して動かず、間違いも報告しなかった.
以前の単例生成方法ではデッドサイクルが実行され,追跡すると関数呼び出しNが多く,ずっと詰まっていたが,スタックは間もなく爆発すると推定される.
まとめ:この問題はこのように書いてあるのは一目瞭然で、類が多くて構造が複雑であまり見えなくなって、しかもdebugはとても難解で、後でお菓子を残さなければなりません:
単一インスタンスの初期化時(初期化関数で深さが遍歴したすべてのコードを含む)には、単一インスタンスへの参照は必ず発生しません.