たぶんこれは明らかですが、Objective-Cでクラスプロパティを宣言する方法がわかりません。
クラスごとにディクショナリをキャッシュする必要があり、それをクラスにどのように入れるか疑問に思います。
objective-Cではプロパティに特定の意味がありますが、静的変数に相当するものを意味すると思いますか?例えば。すべてのタイプのFooに対して1つのインスタンスのみですか?
Objective-Cでクラス関数を宣言するには、-の代わりに+プレフィックスを使用するため、実装は次のようになります。
// Foo.h
@interface Foo {
}
+ (NSDictionary *)dictionary;
// Foo.m
+ (NSDictionary *)dictionary {
static NSDictionary *fooDict = nil;
if (fooDict == nil) {
// create dict
}
return fooDict;
}
私はこのソリューションを使用しています:
@interface Model
+ (int) value;
+ (void) setValue:(int)val;
@end
@implementation Model
static int value;
+ (int) value
{ @synchronized(self) { return value; } }
+ (void) setValue:(int)val
{ @synchronized(self) { value = val; } }
@end
そして、Singletonパターンの代替として非常に有用であることがわかりました。
使用するには、ドット表記でデータにアクセスするだけです:
Model.value = 1;
NSLog(@"%d = value", Model.value);
WWDC 2016/XCode 8で見られるように( LLVMセッションの新機能 @ 5:05)。クラスプロパティは次のように宣言できます
@interface MyType : NSObject
@property (class) NSString *someString;
@end
NSLog(@"format string %@", MyType.someString);
クラスプロパティは決して合成されないことに注意してください
@implementation
static NSString * _someString;
+ (NSString *)someString { return _someString; }
+ (void)setSomeString:(NSString *)newString { _someString = newString; }
@end
@property
と同等のクラスレベルを探している場合、答えは「そのようなものはありません」です。ただし、@property
は、とにかく構文上の砂糖にすぎないことを忘れないでください。適切な名前のオブジェクトメソッドを作成するだけです。
他の人が言ったように、わずかに異なる構文を持つ静的変数にアクセスするクラスメソッドを作成します。
スレッドセーフな方法は次のとおりです。
// Foo.h
@interface Foo {
}
+(NSDictionary*) dictionary;
// Foo.m
+(NSDictionary*) dictionary
{
static NSDictionary* fooDict = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
// create dict
});
return fooDict;
}
これらの編集により、fooDictが一度だけ作成されることが保証されます。
From Apple documentation : "dispatch_once-アプリケーションの有効期間中、ブロックオブジェクトを一度だけ実行します。"
Xcode 8現在、Objective-Cはクラスプロパティをサポートしています。
@interface MyClass : NSObject
@property (class, nonatomic, assign, readonly) NSUUID* identifier;
@end
クラスプロパティは決して合成されないため、独自の実装を記述する必要があります。
@implementation MyClass
static NSUUID*_identifier = nil;
+ (NSUUID *)identifier {
if (_identifier == nil) {
_identifier = [[NSUUID alloc] init];
}
return _identifier;
}
@end
クラス名に通常のドット構文を使用して、クラスプロパティにアクセスします。
MyClass.identifier;
プロパティは、クラスではなくオブジェクトにのみ値を持ちます。
クラスのすべてのオブジェクトに対して何かを保存する必要がある場合は、グローバル変数を使用する必要があります。実装ファイルでstatic
を宣言することで非表示にできます。
オブジェクト間の特定の関係の使用を検討することもできます。マスターの役割をクラスの特定のオブジェクトに関連付け、他のオブジェクトをこのマスターにリンクします。マスターは辞書を単純なプロパティとして保持します。 Cocoaアプリケーションのビュー階層に使用されるツリーのようなものだと思います。
別のオプションは、「クラス」辞書とこの辞書に関連するすべてのオブジェクトのセットの両方で構成される専用クラスのオブジェクトを作成することです。これは、CocoaのNSAutoreleasePool
のようなものです。
Xcode 8以降では、Berbieが回答したclassプロパティ属性を使用できます。
ただし、実装では、iVarの代わりに静的変数を使用して、クラスプロパティのクラスゲッターとセッターの両方を定義する必要があります。
Sample.h
@interface Sample: NSObject
@property (class, retain) Sample *sharedSample;
@end
Sample.m
@implementation Sample
static Sample *_sharedSample;
+ ( Sample *)sharedSample {
if (_sharedSample==nil) {
[Sample setSharedSample:_sharedSample];
}
return _sharedSample;
}
+ (void)setSharedSample:(Sample *)sample {
_sharedSample = [[Sample alloc]init];
}
@end
クラスレベルのプロパティが多数ある場合、シングルトンパターンが適切である可能性があります。このようなもの:
// Foo.h
@interface Foo
+ (Foo *)singleton;
@property 1 ...
@property 2 ...
@property 3 ...
@end
そして
// Foo.m
#import "Foo.h"
@implementation Foo
static Foo *_singleton = nil;
+ (Foo *)singleton {
if (_singleton == nil) _singleton = [[Foo alloc] init];
return _singleton;
}
@synthesize property1;
@synthesize property2;
@synthesise property3;
@end
次のように、クラスレベルのプロパティにアクセスします。
[Foo singleton].property1 = value;
value = [Foo singleton].property2;