Risposte:
le proprietà hanno un significato specifico in Objective-C, ma penso che intendi qualcosa che equivale a una variabile statica? Ad esempio solo un'istanza per tutti i tipi di Foo?
Per dichiarare le funzioni di classe in Objective-C si usa il prefisso + invece di - quindi l'implementazione sarebbe simile a:
// Foo.h
@interface Foo {
}
+ (NSDictionary *)dictionary;
// Foo.m
+ (NSDictionary *)dictionary {
static NSDictionary *fooDict = nil;
if (fooDict == nil) {
// create dict
}
return fooDict;
}
.
sintassi -accessor non è legata alle proprietà in Objective-C, è solo una scorciatoia compilata per qualsiasi metodo che restituisce qualcosa senza prendere argomenti. In questo caso lo preferirei: preferisco personalmente la .
sintassi per qualsiasi utilizzo in cui il codice client intende ottenere qualcosa, non eseguire un'azione (anche se il codice di implementazione può creare qualcosa una volta o eseguire azioni con effetti collaterali) . La .
sintassi per un uso intenso comporta anche un codice più leggibile: la presenza di […]
s significa che si sta facendo qualcosa di significativo quando si recupera .
invece la sintassi.
Sto usando questa soluzione:
@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
E l'ho trovato estremamente utile in sostituzione del modello Singleton.
Per usarlo, accedi semplicemente ai tuoi dati con la notazione a punti:
Model.value = 1;
NSLog(@"%d = value", Model.value);
self
significa all'interno di un metodo di classe?
self
è l'oggetto che ha ricevuto il messaggio . E poiché anche le classi sono oggetti , in questo caso self
significaModel
@synchronized
?
Come visto in WWDC 2016 / XCode 8 ( novità della sessione LLVM @ 5: 05). Le proprietà della classe possono essere dichiarate come segue
@interface MyType : NSObject
@property (class) NSString *someString;
@end
NSLog(@"format string %@", MyType.someString);
Si noti che le proprietà della classe non vengono mai sintetizzate
@implementation
static NSString * _someString;
+ (NSString *)someString { return _someString; }
+ (void)setSomeString:(NSString *)newString { _someString = newString; }
@end
static
variabile ( ) deve ancora essere dichiarata e utilizzata e i metodi implementati esplicitamente, proprio come in precedenza. La sintassi del punto ha già funzionato anche in precedenza. In tutto, sembra un affare più grande di quello che è in realtà.
Se stai cercando l'equivalente a livello di classe @property
, allora la risposta è "non esiste nulla di simile". Ma ricorda, @property
è solo zucchero sintattico, comunque; crea solo metodi oggetto con nomi appropriati.
Volete creare metodi di classe che accedano a variabili statiche che, come altri hanno già detto, hanno solo una sintassi leggermente diversa.
UIDevice.currentDevice.identifierForVendor
per me va bene.
Ecco un modo sicuro per farlo:
// 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;
}
Queste modifiche assicurano che fooDict sia creato una sola volta.
Dalla documentazione Apple : "dispatch_once - Esegue un oggetto blocco una e una sola volta per la durata di un'applicazione".
Initializer element is not a compile-time constant
.
A partire da Xcode 8 Objective-C ora supporta le proprietà di classe:
@interface MyClass : NSObject
@property (class, nonatomic, assign, readonly) NSUUID* identifier;
@end
Poiché le proprietà della classe non vengono mai sintetizzate, è necessario scrivere la propria implementazione.
@implementation MyClass
static NSUUID*_identifier = nil;
+ (NSUUID *)identifier {
if (_identifier == nil) {
_identifier = [[NSUUID alloc] init];
}
return _identifier;
}
@end
Si accede alle proprietà della classe usando la normale sintassi del punto sul nome della classe:
MyClass.identifier;
Le proprietà hanno valori solo negli oggetti, non nelle classi.
Se devi archiviare qualcosa per tutti gli oggetti di una classe, devi utilizzare una variabile globale. Puoi nasconderlo dichiarandolo static
nel file di implementazione.
Puoi anche considerare l'utilizzo di relazioni specifiche tra i tuoi oggetti: attribuisci un ruolo di maestro a un oggetto specifico della tua classe e colleghi altri oggetti a questo maestro. Il master manterrà il dizionario come una semplice proprietà. Penso a un albero come quello usato per la gerarchia delle viste nelle applicazioni Cocoa.
Un'altra opzione è quella di creare un oggetto di una classe dedicata composto sia dal tuo dizionario di "classe" sia da un insieme di tutti gli oggetti relativi a questo dizionario. Questo è qualcosa di simile NSAutoreleasePool
al cacao.
A partire da Xcode 8, è possibile utilizzare l' attributo della proprietà class come risposto da Berbie.
Tuttavia, nell'implementazione, è necessario definire sia il getter di classe che il setter per la proprietà della classe utilizzando una variabile statica al posto di un 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
Se si dispone di molte proprietà a livello di classe, potrebbe essere in ordine un modello singleton. Qualcosa come questo:
// Foo.h
@interface Foo
+ (Foo *)singleton;
@property 1 ...
@property 2 ...
@property 3 ...
@end
E
// 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
Ora accedi alle tue proprietà a livello di classe come questa:
[Foo singleton].property1 = value;
value = [Foo singleton].property2;
dispatch_once
qui.
[Prova questa soluzione è semplice] Puoi creare una variabile statica in una classe Swift e chiamarla da qualsiasi classe Objective-C.