Como faço para declarar propriedades de nível de class no Objective-C?

Talvez isso seja óbvio, mas não sei como declarar propriedades de class em Objective-C.

Eu preciso armazenar em cache um dictionary por class e me pergunto como colocá-lo na class.

propriedades têm um significado específico em Objective-C, mas eu acho que você quer dizer algo que é equivalente a uma variável estática? Por exemplo, apenas uma instância para todos os tipos de Foo?

Para declarar funções de class em Objective-C, você usa o prefixo + em vez de – assim sua implementação seria algo como:

// Foo.h @interface Foo { } + (NSDictionary *)dictionary; // Foo.m + (NSDictionary *)dictionary { static NSDictionary *fooDict = nil; if (fooDict == nil) { // create dict } return fooDict; } 

Estou usando esta solução:

 @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 eu achei extremamente útil como um substituto do padrão Singleton.

Para usá-lo, basta acessar seus dados com notação de ponto:

 Model.value = 1; NSLog(@"%d = value", Model.value); 

Se você está procurando o equivalente no nível de class de @property , então a resposta é “não existe tal coisa”. Mas lembre-se, @property é apenas açúcar sintático, de qualquer maneira; apenas cria methods de object apropriadamente nomeados.

Você deseja criar methods de class que acessem variables ​​estáticas que, como já foi dito, possuem apenas uma syntax ligeiramente diferente.

Como visto no WWDC 2016 / XCode 8 (o que há de novo na session LLVM @ 5: 05). Propriedades de class podem ser declaradas da seguinte forma

 @interface MyType : NSObject @property (class) NSString *someString; @end NSLog(@"format string %@", MyType.someString); 

Observe que as propriedades de class nunca são sintetizadas

 @implementation static NSString * _someString + (NSString *)someString { return _someString; } + (void)setSomeString:(NSString *)newString { _someString = newString; } @end 

Aqui está uma maneira segura de fazer isso:

 // 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; } 

Essas edições garantem que o fooDict seja criado apenas uma vez.

Da documentação da Apple : “dispatch_once – Executa um object de bloco uma vez e somente uma vez para o tempo de vida de um aplicativo.”

A partir do Xcode 8 Objective-C agora suporta propriedades de class:

 @interface MyClass : NSObject @property (class, nonatomic, assign, readonly) NSUUID* identifier; @end 

Como as propriedades de class nunca são sintetizadas, você precisa escrever sua própria implementação.

 @implementation MyClass static NSUUID*_identifier = nil; + (NSUUID *)identifier { if (_identifier == nil) { _identifier = [[NSUUID alloc] init]; } return _identifier; } @end 

Você acessa as propriedades da class usando a syntax de ponto normal no nome da class:

 MyClass.identifier; 

Propriedades possuem valores apenas em objects, não em classs.

Se você precisa armazenar algo para todos os objects de uma class, você tem que usar uma variável global. Você pode ocultá-lo, declarando-o static no arquivo de implementação.

Você também pode considerar o uso de relações específicas entre seus objects: você atribui um papel de mestre a um object específico de sua class e vincula outros objects a esse mestre. O mestre manterá o dictionary como uma propriedade simples. Penso em uma tree como a usada para a hierarquia de visualizações em aplicativos Cocoa.

Outra opção é criar um object de uma class dedicada que seja composta tanto pelo dictionary de ‘classs’ quanto pelo conjunto de todos os objects relacionados a este dictionary. Isso é algo como NSAutoreleasePool em Cocoa.

Se você tiver muitas propriedades de nível de class, um padrão singleton poderá estar em ordem. Algo assim:

 // 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 

Agora, acesse suas propriedades no nível da aula assim:

 [Foo singleton].property1 = value; value = [Foo singleton].property2; 

A partir do Xcode 8, você pode usar o atributo de propriedade de class como respondido por Berbie.

No entanto, na implementação, você precisa definir getter e setter de class para a propriedade de class usando uma variável estática em vez de um 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 

[Tente esta solução é simples] Você pode criar uma variável estática em uma class Swift e chamá-lo de qualquer class Objective-C.