Objetivo C Variáveis ​​estáticas de class de class

Eu tenho uma class de filme, cada um dos quais armazena uma identificação única. Em C #, Java etc eu posso definir um static currentID atual e cada vez que eu definir o ID i pode aumentar o currentID e a mudança ocorre no nível de class não nível de object. Isso pode ser feito no Objective C? Eu achei muito difícil encontrar uma resposta para isso.

   

Descrição do problema :

  1. Você quer que sua ClassA tenha uma variável de class ClassB.
  2. Você está usando o Objective-C como linguagem de programação.
  3. O Objective-C não suporta variables ​​de class como o C ++.

Uma alternativa :

Simule um comportamento de variável de class usando resources do Objective-C

  1. Declare / Defina uma variável estática dentro da classA.m para que ela seja acessível apenas para os methods classA (e tudo que você colocar dentro da classA.m).

  2. Sobrescreva o método de class de boot NSObject para inicializar apenas uma vez a variável estática com uma instância de ClassB.

  3. Você vai estar se perguntando, por que eu deveria replace o método de boot NSObject. A documentação da Apple sobre este método tem a resposta: “O tempo de execução envia inicializar para cada class em um programa exatamente uma vez antes da class, ou qualquer class que herda dele, é enviada sua primeira mensagem de dentro do programa. pode nunca ser invocado se a class não for usada.) “.

  4. Sinta-se à vontade para usar a variável estática em qualquer método de class / instância de ClassA.

Amostra de código :

arquivo: classA.m

static ClassB *classVariableName = nil; @implementation ClassA ... +(void) initialize { if (! classVariableName) classVariableName = [[ClassB alloc] init]; } +(void) classMethodName { [classVariableName doSomething]; } -(void) instanceMethodName { [classVariableName doSomething]; } ... @end 

Referências :

  1. Variáveis ​​de class explicadas comparando as abordagens de Objective-C e C ++

No seu arquivo .m, você pode declarar uma variável como estática:

 static ClassName *variableName = nil; 

Então você pode inicializá-lo em seu método de +(void)initialize .

Por favor, note que esta é uma variável estática C simples e não é estática no sentido de Java ou C # considerá-lo, mas trará resultados semelhantes.

A partir do Xcode 8, você pode definir propriedades de class em Obj-C. Isso foi adicionado para interoperar com as propriedades estáticas do Swift.

O Objective-C agora suporta propriedades de class, que interoperam com as propriedades do tipo Swift. Eles são declarados como: @property (class) NSString * someStringProperty ;. Eles nunca são sintetizados. (23891898)

Aqui está um exemplo

 @interface YourClass : NSObject @property (class, nonatomic, assign) NSInteger currentId; @end @implementation YourClass static NSInteger _currentId = 0; + (NSInteger)currentId { return _currentId; } + (void)setCurrentId:(NSInteger)newValue { _currentId = newValue; } @end 

Então você pode acessá-lo assim:

 YourClass.currentId = 1; val = YourClass.currentId; 

Aqui está um post explicativo muito interessante que usei como referência para editar essa resposta antiga.


2011 Resposta: (não use isso, é terrível)

Se você realmente não quer declarar uma variável global, existe outra opção, talvez não muito ortodoxa :-), mas funciona … Você pode declarar um método “get & set” como este, com uma variável estática dentro de:

 + (NSString*)testHolder:(NSString*)_test { static NSString *test; if(_test != nil) { if(test != nil) [test release]; test = [_test retain]; } // if(test == nil) // test = @"Initialize the var here if you need to"; return test; } 

Então, se você precisa obter o valor, basta ligar:

 NSString *testVal = [MyClass testHolder:nil] 

E então, quando você quiser configurá-lo:

 [MyClass testHolder:testVal] 

Caso você queira poder definir este pseudo-estático-var como nulo, você pode declarar testHolder como este:

 + (NSString*)testHolderSet:(BOOL)shouldSet newValue:(NSString*)_test { static NSString *test; if(shouldSet) { if(test != nil) [test release]; test = [_test retain]; } return test; } 

E dois methods úteis:

 + (NSString*)test { return [MyClass testHolderSet:NO newValue:nil]; } + (void)setTest:(NSString*)_test { [MyClass testHolderSet:YES newValue:_test]; } 

Espero que ajude! Boa sorte.

No seu arquivo .m, declare uma variável global de arquivo:

 static int currentID = 1; 

então na sua rotina de boot, referince que:

 - (id) init { self = [super init]; if (self != nil) { _myID = currentID++; // not thread safe } return self; } 

ou se precisar mudar em algum outro momento (por exemplo, no seu método openConnection), então incremente-o lá. Lembre-se de que ele não é thread safe como é, você precisará sincronizar (ou melhor ainda, usar um add atômico) se houver algum problema de threading.

Como o pgb disse, não há “variables ​​de class”, apenas “variables ​​de instância”. A maneira objetiva-c de fazer variables ​​de class é uma variável global estática dentro do arquivo .m da class. A “estática” garante que a variável não possa ser usada fora desse arquivo (ou seja, não pode ser externa).

Aqui seria uma opção:

 +(int)getId{ static int id; //Do anything you need to update the ID here return id; } 

Note que este método será o único método para acessar id, então você terá que atualizá-lo de alguma forma neste código.

(Estritamente falando, não uma resposta para a pergunta, mas na minha experiência provavelmente será útil ao procurar por variables ​​de class)

Um método de class pode muitas vezes desempenhar muitas das funções que uma variável de class teria em outras linguagens (por exemplo, configuração alterada durante os testes):

 @interface MyCls: NSObject + (NSString*)theNameThing; - (void)doTheThing; @end @implementation + (NSString*)theNameThing { return @"Something general"; } - (void)doTheThing { [SomeResource changeSomething:[self.class theNameThing]]; } @end @interface MySpecialCase: MyCls @end @implementation + (NSString*)theNameThing { return @"Something specific"; } @end 

Agora, um object da class MyCls chama Resource:changeSomething: com a string @"Something general" em uma chamada para doTheThing: mas um object derivado de MySpecialCase com a string @"Something specific" .

Você pode renomear a class como classA.mm e adicionar resources C ++ nela.

Outra possibilidade seria ter um pequeno singleton de subclass NSNumber.