Variables de nivel de clase estática de Objective C

Tengo una película de clase, cada una de las cuales almacena una identificación única. En C #, Java, etc., puedo definir un staticID actual static y cada vez que configuro el ID, puedo boost el currentID y el cambio ocurre en el nivel de clase, no en el nivel de objeto. ¿Se puede hacer esto en Objective C? Me ha resultado muy difícil encontrar una respuesta para esto.

Descripción del problema :

  1. Desea que su ClassA tenga una variable de clase ClassB.
  2. Está utilizando Objective-C como lenguaje de progtwigción.
  3. Objective-C no admite variables de clase como C ++.

Una alternativa :

Simular un comportamiento de variable de clase utilizando las características de Objective-C

  1. Declare / Define una variable estática dentro de la claseA.m por lo que solo será accesible para los métodos de clase A (y todo lo que coloque dentro de la clase A.m).

  2. Sobrescriba el método de clase de inicialización de NSObject para inicializar una sola vez la variable estática con una instancia de ClassB.

  3. Se preguntará, ¿por qué debería sobrescribir el método de inicialización de NSObject? La documentación de Apple sobre este método tiene la respuesta: “El tiempo de ejecución envía inicializar a cada clase en un progtwig exactamente una vez justo antes de que la clase, o cualquier clase que herede de ella, se envíe su primer mensaje desde el progtwig. (Por lo tanto, el método nunca se invocará si la clase no se usa). “.

  4. Siéntase libre de usar la variable estática dentro de cualquier clase ClassA / método de instancia.

Muestra de código :

archivo: 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 

Referencias

  1. Variables de clase explicadas que comparan los enfoques de Objective-C y C ++

En su archivo .m, puede declarar una variable como estática:

 static ClassName *variableName = nil; 

Entonces puede inicializarlo en su método de +(void)initialize .

Tenga en cuenta que esta es una variable estática simple de C y no es estática en el sentido en que Java o C # la consideran, pero arrojará resultados similares.

A partir de Xcode 8, puede definir propiedades de clase en Obj-C. Esto se ha agregado para interoperar con las propiedades estáticas de Swift.

Objective-C ahora admite propiedades de clase, que interoperan con propiedades de tipo Swift. Se declaran como: @property (clase) NSString * someStringProperty ;. Ellos nunca son sintetizados. (23891898)

Aquí hay un ejemplo

 @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 

Entonces puedes acceder de esta manera:

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

Aquí hay una publicación explicativa muy interesante que utilicé como referencia para editar esta vieja respuesta.


Respuesta de 2011: (no uses esto, es terrible)

Si realmente no quieres declarar una variable global, existe otra opción, tal vez no muy ortodoxa :-), pero funciona … Puedes declarar un método “get & set” como este, con una variable estática dentro:

 + (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; } 

Entonces, si necesita obtener el valor, solo llame:

 NSString *testVal = [MyClass testHolder:nil] 

Y luego, cuando quieras configurarlo:

 [MyClass testHolder:testVal] 

En el caso de que desee poder establecer este pseudo-static-var en nil, puede declarar testHolder esta forma:

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

Y dos métodos útiles:

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

¡Espero eso ayude! Buena suerte.

En su archivo .m, declare una variable global de archivo:

 static int currentID = 1; 

luego en su rutina de inicio, refiérase a eso:

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

o si necesita cambiar en algún otro momento (por ejemplo, en su método openConnection), luego increméntelo allí. Recuerda que no es seguro para subprocesos, necesitarás sincronizar (o mejor aún, usar un complemento atómico) si hay problemas con el subprocesamiento.

Como dijo pgb, no hay “variables de clase”, solo “variables de instancia”. La forma objective c de hacer variables de clase es una variable global estática dentro del archivo .m de la clase. El “estático” asegura que la variable no se puede usar fuera de ese archivo (es decir, no puede ser externa).

Aquí hay una opción:

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

Tenga en cuenta que este método será el único método para acceder a la identificación, por lo que tendrá que actualizarlo de alguna manera en este código.

(Estrictamente hablando, no es una respuesta a la pregunta, pero en mi experiencia probablemente sea útil cuando busco variables de clase)

Un método de clase a menudo puede desempeñar muchos de los roles que una variable de clase tendría en otros idiomas (por ejemplo, la configuración modificada durante las pruebas):

 @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 

Ahora, un objeto de la clase MyCls llama a Resource:changeSomething: con la cadena @"Something general" sobre una llamada a doTheThing: pero un objeto derivado de MySpecialCase con la cadena @"Something specific" .

Puede cambiar el nombre de la clase como classA.mm y agregarle características de C ++.

Otra posibilidad sería tener una pequeña subclase NSNumber singleton.