Antworten:
Eigenschaften haben in Objective-C eine bestimmte Bedeutung, aber ich denke, Sie meinen etwas, das einer statischen Variablen entspricht? ZB nur eine Instanz für alle Arten von Foo?
Um Klassenfunktionen in Objective-C zu deklarieren, verwenden Sie das Präfix + anstelle von - Ihre Implementierung sieht also ungefähr so aus:
// Foo.h
@interface Foo {
}
+ (NSDictionary *)dictionary;
// Foo.m
+ (NSDictionary *)dictionary {
static NSDictionary *fooDict = nil;
if (fooDict == nil) {
// create dict
}
return fooDict;
}
.
Syntax -accessor ist nicht an Eigenschaften in Objective-C gebunden, sondern lediglich eine kompilierte Verknüpfung für jede Methode, die etwas zurückgibt, ohne Argumente zu verwenden. In diesem Fall würde ich es vorziehen - ich persönlich bevorzuge die .
Syntax für jede Verwendung, bei der der Client-Code etwas abrufen und keine Aktion ausführen möchte (selbst wenn der Implementierungscode möglicherweise einmal etwas erstellt oder Nebenwirkungen ausführt) . Eine .
Syntax mit starker Nutzung führt auch zu besser lesbarem Code: Das Vorhandensein von […]
s bedeutet, dass etwas Bedeutendes getan wird, wenn Abrufe .
stattdessen Syntax verwenden.
Ich benutze diese Lösung:
@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
Und ich fand es äußerst nützlich als Ersatz für das Singleton-Muster.
Um es zu verwenden, greifen Sie einfach mit Punktnotation auf Ihre Daten zu:
Model.value = 1;
NSLog(@"%d = value", Model.value);
self
bedeutet innerhalb einer Klassenmethode?
self
ist das Objekt, das die Nachricht empfangen hat . Und da Klassen sind auch Objekte , in diesem Fall self
MittelModel
@synchronized
?
Wie in WWDC 2016 / XCode 8 zu sehen ( was ist neu in der LLVM-Sitzung um 5: 05). Klasseneigenschaften können wie folgt deklariert werden
@interface MyType : NSObject
@property (class) NSString *someString;
@end
NSLog(@"format string %@", MyType.someString);
Beachten Sie, dass Klasseneigenschaften niemals synthetisiert werden
@implementation
static NSString * _someString;
+ (NSString *)someString { return _someString; }
+ (void)setSomeString:(NSString *)newString { _someString = newString; }
@end
static
) Variable muss weiterhin deklariert und verwendet werden, und die Methoden müssen explizit wie zuvor implementiert werden. Die Punktsyntax hat auch schon früher funktioniert. Alles in allem klingt dies nach einer größeren Sache als es wirklich ist.
Wenn Sie nach dem Äquivalent auf Klassenebene suchen @property
, lautet die Antwort "Es gibt so etwas nicht". Aber denken Sie daran, @property
ist sowieso nur syntaktischer Zucker; Es werden nur Objektmethoden mit entsprechendem Namen erstellt.
Sie möchten Klassenmethoden erstellen, die auf statische Variablen zugreifen, die, wie andere gesagt haben, nur eine geringfügig andere Syntax haben.
UIDevice.currentDevice.identifierForVendor
funktioniert bei mir.
Hier ist eine thread-sichere Methode:
// 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;
}
Diese Änderungen stellen sicher, dass fooDict nur einmal erstellt wird.
Aus der Apple-Dokumentation : "dispatch_once - Führt ein Blockobjekt einmal und nur einmal für die Lebensdauer einer Anwendung aus."
Initializer element is not a compile-time constant
.
Ab Xcode 8 unterstützt Objective-C jetzt Klasseneigenschaften:
@interface MyClass : NSObject
@property (class, nonatomic, assign, readonly) NSUUID* identifier;
@end
Da Klasseneigenschaften niemals synthetisiert werden, müssen Sie Ihre eigene Implementierung schreiben.
@implementation MyClass
static NSUUID*_identifier = nil;
+ (NSUUID *)identifier {
if (_identifier == nil) {
_identifier = [[NSUUID alloc] init];
}
return _identifier;
}
@end
Sie greifen auf die Klasseneigenschaften mit der normalen Punktsyntax für den Klassennamen zu:
MyClass.identifier;
Eigenschaften haben Werte nur in Objekten, nicht in Klassen.
Wenn Sie etwas für alle Objekte einer Klasse speichern müssen, müssen Sie eine globale Variable verwenden. Sie können es ausblenden, indem Sie es static
in der Implementierungsdatei deklarieren .
Sie können auch bestimmte Beziehungen zwischen Ihren Objekten verwenden: Sie weisen einem bestimmten Objekt Ihrer Klasse eine Masterrolle zu und verknüpfen andere Objekte mit diesem Master. Der Master hält das Wörterbuch als einfache Eigenschaft. Ich stelle mir einen Baum vor, wie er für die Ansichtshierarchie in Cocoa-Anwendungen verwendet wird.
Eine andere Möglichkeit besteht darin, ein Objekt einer dedizierten Klasse zu erstellen, das sowohl aus Ihrem Klassenwörterbuch als auch aus einer Reihe aller mit diesem Wörterbuch verbundenen Objekte besteht. Das ist so etwas wie NSAutoreleasePool
in Kakao.
Ab Xcode 8 können Sie das von Berbie beantwortete Klasseneigenschaftsattribut verwenden .
In der Implementierung müssen Sie jedoch sowohl den Klassen-Getter als auch den Setter für die Klasseneigenschaft mithilfe einer statischen Variablen anstelle eines iVar definieren.
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
Wenn Sie viele Eigenschaften auf Klassenebene haben, ist möglicherweise ein Singleton-Muster in Ordnung. Etwas wie das:
// Foo.h
@interface Foo
+ (Foo *)singleton;
@property 1 ...
@property 2 ...
@property 3 ...
@end
Und
// 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
Greifen Sie jetzt wie folgt auf Ihre Eigenschaften auf Klassenebene zu:
[Foo singleton].property1 = value;
value = [Foo singleton].property2;
dispatch_once
hier ein zu verwenden.
[Probieren Sie diese Lösung einfach aus] Sie können eine statische Variable in einer Swift-Klasse erstellen und sie dann von jeder Objective-C-Klasse aus aufrufen.