回答:
プロパティは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;
}
.
-accessor構文はObjective-Cの内のプロパティに縛られていない、それはちょうどコンパイル時にショートカットのいずれかの方法のためにその任意の引数を取ることなく、リターンの何かが。この場合、私はそれを好み.
ます。私は個人的に、クライアントコードがアクションを実行するのではなく、何かを取得するつもりの構文を好みます(実装コードが何かを作成したり、副作用アクションを実行したりする場合でも)。使用頻度の.
高い構文でもコードが読みやすくなります。sの存在は[…]
、フェッチが.
構文を使用するときに重要なことが行われていることを意味します。
私はこのソリューションを使用しています:
@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
そして、私はそれがシングルトンパターンの置き換えとして非常に役立つとわかりました。
使用するには、ドット表記でデータにアクセスします。
Model.value = 1;
NSLog(@"%d = value", Model.value);
self
、クラスメソッド内ではいったい何を意味するのでしょうか。
@synchronized
か?
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
static
。以前と同じように、()変数を宣言して使用し、メソッドを明示的に実装する必要があります。以前にもドット構文は機能していました。全体として、これは実際よりも大きな問題のように聞こえます。
クラスレベルでと同等のものを探している場合@property
、答えは「そのようなものはありません」です。でも覚えておいて、@property
てください。とにかく、構文上の砂糖だけです。適切な名前のオブジェクトメソッドを作成するだけです。
他の人が言ったように、わずかに異なる構文しか持たない静的変数にアクセスするクラスメソッドを作成したいとします。
UIDevice.currentDevice.identifierForVendor
私のために働く。
スレッドセーフな方法を次に示します。
// 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が1度だけ作成されることが保証されます。
Appleのドキュメントから:「dispatch_once-ブロックオブジェクトを、アプリケーションの存続期間中に一度だけ実行します。」
Initializer element is not a compile-time constant
。
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アプリケーションのビュー階層に使用されているようなツリーを思い浮かべます。
別のオプションは、「クラス」辞書と、この辞書に関連するすべてのオブジェクトのセットの両方で構成される専用クラスのオブジェクトを作成することです。これはNSAutoreleasePool
ココアのようなものです。
Xcode 8以降では、Berbieが回答したクラスプロパティ属性を使用できます。
ただし、実装では、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;
dispatch_once
ここで使うのはかなり簡単でしょう。