2011-12-07 2 views
1

Objective-Cでローカル静的オブジェクトを使用するにはどうすればよいですか?Objective-Cでローカル静的オブジェクトを使用するには?

- (void)foo { 
    static NSMutableArray *mutableArr = nil; 
    // initialize mutableArr somehow somewhere 
    // using mutableArr several times 
} 
+0

@KevinBallardはい、Objective-Cがそれをサポートしている可能性があります。 – Nickolas

+0

@KevinBallard Cでは、参照カウントを気にする必要はありません。ここではカウントを保持して、ある時点でそれをリリースする必要があります。私はそれを行う簡単な方法があるのだろうかと思います。 – Nickolas

+4

@Nickolas:静的変数は、プログラムの存続期間中存在します。なぜオブジェクトに通常のオブジェクトの寿命を持たせたいのですか?あなたが想像している使用法について何か不足していると思います。 – Chuck

答えて

0

私は何が不足していないよ願っていますが、これは、私はそれを使用している方法です:

- (void)foo { 
    static NSMutableArray *mutableArr = nil; 
    if (mutableArr == nil) { 
     mutableArr = [[NSMutableArray alloc] init...]; 
     // add more first time initialization as required 
    } 
    assert(mutableArr); 
    // now, use mutableArr freely... 
} 
+0

FWIWでは、複数のスレッドからの同時アクセスではスレッドセーフではありません。つまり、単一の変更可能なデータ構造への共有参照を販売している場合は、既にこのメソッドのすべての呼び出し元のスレッドセーフティを実行しています。 – ipmcc

0

static var。 initをvarに設定する前に初期化されているかどうかを確認するのは良い方法です。

5

あなたの目標は、シングルトンを持っているだけであるならば、それは、これらのための一般的な、受け入れパターンらしいです日以下のとおりである。

#import <dispatch/dispatch.h> 

+ (NSMyObjectType*)sharedMyObject 
{ 
    static dispatch_once_t pred; 
    static NSMyObjectType* sValue; 
    dispatch_once(&pred, ^{ sValue = [[NSMyObjectType alloc] init]; }); 
    return sValue; 
} 

これはNSMyObjectTypeは不変であると仮定すると、NSMyObjectTypeのインスタンスが漏れに関して、複数のスレッドからの同時アクセスのために安全になります。また、別の理由(例えば特定の@protocolの採用)が必要な場合を除いて、インスタンスメソッドの代わりにそのようなアクセサをクラスメソッドにするのは理にかなっています。これは、APIコンシューマに、共有リソースであるというヒントを与えます(メソッド名にsharedという単語を使用した場合と同じです)。

複数のスレッドからの同時アクセスのための可変共有データ構造を販売している場合は、そのような使用のために本質的に安全なタイプを使用するか、APIベンダーとしてその安全を自分自身で提供したいと考えています。あなたが提供する、不変のコピーとしてセット全体を実際の根本的な可変オブジェクトへのアクセスとその突然変異を同期、自動販売することで

@class NSFoo; 

@interface SharedFooVender : NSObject 

+ (NSSet*)sharedFoos; 
+ (void)addSharedFoo:(NSFoo*)foo; 
+ (void)removeSharedFoo:(NSFoo*)foo; 

@end 

@implementation SharedFooVender 

static NSMutableSet* pPrivateSharedMutableSetOfFoos() 
{ 
    static NSMutableSet* sSetOfFoos = nil; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
     sSetOfFoos = [[NSMutableSet alloc] init]; 
    }); 
    return sSetOfFoos; 
} 

+ (NSSet*)sharedFoos 
{ 
    NSMutableSet* sharedFoos = pPrivateSharedMutableSetOfFoos(); 
    @synchronized(sharedFoos) 
    { 
     return [[sharedFoos copy] autorelease]; 
    }  
} 

+ (void)addSharedFoo:(NSFoo*)foo 
{ 
    if (nil == foo) return; 
    NSMutableSet* sharedFoos = pPrivateSharedMutableSetOfFoos(); 
    @synchronized(sharedFoos) 
    { 
     [sharedFoos addObject: foo]; 
    } 
} 

+ (void)removeSharedFoo:(NSFoo*)foo 
{ 
    if (nil == foo) return; 
    NSMutableSet* sharedFoos = pPrivateSharedMutableSetOfFoos(); 
    @synchronized(sharedFoos) 
    { 
     [sharedFoos removeObject: foo]; 
    } 
} 

@end 

:あなたはNSMutableSetをVENDしたい場合たとえば、あなたはこのような何かを行う可能性があります複数のスレッドからの同時アクセスのための安全性(不変のコピーを作成することによって、消費者は古いコピーにハングアップができることに留意されたい、そして本質的には、すべての不変のコピーは、それが作成のインスタントから陳腐であると想定すべきである。)

FWIWには、これに対して数百万の異なるアプローチがあります - 私は、このアプローチがすべての(またはいずれのシナリオでも)完璧だと主張していません。しかし、あなたのためのロックを提供するためにあなたのAPIの消費者に頼ることは、災害のためのレシピです。

今や、シングルスレッドアクセスのみが許可されていると仮定すると、受け入れられた答えは問題ありません。これをメインスレッド(おそらくUIKitコンテキスト)からのみ使用すると予想される場合は、受け入れられた回答を使用することができます。[NSThread isMainThread]をアサートして、後で誰かがバックグラウンドスレッドから共有アクセサーを呼び出したときに早く失敗するようにすることをお勧めします。