4

シングルトン パターンのこの特定の実装をどこでも見てきました。

+ (CargoBay *)sharedManager {
   static CargoBay *_sharedManager = nil;
   static dispatch_once_t onceToken;
   dispatch_once(&onceToken, ^{
      _sharedManager = [[CargoBay alloc] init];
   });
   return _sharedManager;
}

そして、それは良い習慣として受け入れられているようです(特にこれはCargoBayからのものです)。

私が理解していない唯一の部分は最初の行static CargoBay *_sharedManager = nil;です。

なぜそのstatic変数を に設定しているのnilですか?

4

2 に答える 2

8

それは、読みやすさ、慣習、および実践の問題です。次の理由により、実際には必要ありません。

1。その値はチェックされません。古いシングルトン実装では、有名な

+ (id)sharedInstance
{
    static SomeClass *shared = nil;
    if (shared == nil)
        shared = [[SomeClass alloc] init];

    return shared;
}

コード - このメソッドが機能するには、バッキング変数を nil に初期化する必要があります。最初に nil でない場合、if 部分の alloc-init が誤って省略され、ジャンク ポインターが返されるためです。ただし、GCD ソリューションでは、nil-check は不要になりました。GCD は「このコードを 1 回だけ実行する」プラグマを処理します。

二。それでも、静的変数は暗黙的にゼロに初期化されます。したがって、単に記述static id shared;しても、最初はnil.

三。なぜこれが良い習慣になるのでしょうか? 前述の最初の 2 つの理由にもかかわらず、何かが明示的にゼロに初期化されていることをソース コードの読者に知らせる方が読みやすいからです。または、静的変数が適切に自動初期化されていない非準拠の実装が存在する可能性もあります。その場合、このアクションが実行されます。

于 2012-09-22T15:03:13.053 に答える
1

クリーンなインスタンスを確実に取得するために、nil に設定しています。

これは、やりたいことのより読みやすいバージョンです。

+ (GlobalVariables *)sharedInstance {
    // the instance of this class is stored here
    static GlobalVariables *myInstance = nil;

    // check to see if an instance already exists
    if (nil == myInstance) {
        myInstance  = [[[self class] alloc] init];
    }
    // return the instance of this class
    return myInstance;
}

しかし、これがスレッドセーフではない可能性があることを示す投稿がたくさんあるので、上記の方法と私が投稿したもののハイブリッドに移動すると、次のようになります。

// Declared outside Singleton Manager    
static SingletonClass *myInstance = nil;
+ (GlobalVariables *)sharedInstance {
    if (nil != myInstance) {
        return myInstance;
    }

    static dispatch_once_t pred;        // Lock
    dispatch_once(&pred, ^{             // This code is called at most once per app
        myInstance = [[GlobalVariables alloc] init];
    });

    return myInstance;
}
于 2012-09-22T15:08:20.933 に答える