¿Variable de clase definida en @implementation en lugar de @interface?

Soy nuevo en Objective-C, pero tengo curiosidad sobre algo que realmente no he visto abordado en ningún otro lado.

¿Podría alguien decirme cuál es la diferencia entre una variable privada que se declara en el bloque @interface versus una variable que se declara dentro del bloque @implementation fuera de los métodos de la clase, es decir:

 @interface Someclass : NSObject { NSString *forExample; } @end 

vs.

 @implementation Someclass NSString *anotherExample; -(void)methodsAndSuch {} @end 

Parece que ambas variables (por forExample , otro anotherExample ) son igualmente accesibles en toda la clase y realmente no puedo encontrar una diferencia en su comportamiento. ¿La segunda forma también se llama una variable de instancia?

Este último no está definiendo una variable de instancia. Más bien, está definiendo una variable global en el archivo .m. Dicha variable no es exclusiva ni parte de ninguna instancia de objeto.

Tales globales tienen sus usos (miembros estáticos de C ++ más o menos equivalentes, por ejemplo, almacenar una instancia de singleton), pero normalmente los definirías en la parte superior del archivo antes de la directiva @implementation.

¡Son muy diferentes! El de @implementation es una variable global no exclusiva de cada instancia. Imagine que hay accesadores para ambas variables, escritos de la manera obvia. Entonces la diferencia de comportamiento se muestra aquí:

 Someclass* firstObject = [[Someclass alloc] init]; Someclass* secondObject = [[Someclass alloc] init]; //forExample is an instance variable, and is unique to each instance. [firstObject setForExample:@"One"]; [secondObject setForExample:@"Two"]; NSLog(@"%@",[firstObject forExample]); //Result: "One" NSLog(@"%@",[secondObject forExample]); //Result: "Two" //anotherExample is a global variable, and is NOT unique to each instance. [firstObject setAnotherExample:@"One"]; [secondObject setAnotherExample:@"Two"]; NSLog(@"%@",[firstObject anotherExample]); //Result: "Two" (!) NSLog(@"%@",[secondObject anotherExample]); //Result: "Two" //Both instances return "Two" because there is only ONE variable this time. //When secondObject set it, it replaced the value that firstObject set. 

Si está buscando este tipo de comportamiento, es mejor que use una variable de clase, como esta:

 static NSString* yetAnotherExample = nil; 

Luego puede usar métodos de clase para interactuar con la variable, y es claramente específico de la clase (a diferencia de la instancia específica o global).

Si declara una variable dentro de la sección @implementation, en realidad está creando una variable global, visible en todas partes (en todos los métodos de su aplicación).

Las variables miembro solo se pueden declarar en la sección @interface. Solo son accesibles en la clase en sí.

El bloque privado declarado dentro del bloque @implementation es algo peligroso, me parece, en comparación con otro concepto de OOP, por ejemplo, Java. Parece una variable miembro pero estática.

El progtwigdor principiante puede engañarlo fácilmente. Escribo un progtwig de prueba y sorprendido con el comportamiento.

 @interface SomeClass : NSObject { NSString *forExample; } - (void) set:(NSString *)one another:(NSString *)another; - (void)print; @end 

Implementación:

 #import "SomeClass.h" @implementation SomeClass NSString *anotherExample; - (void) set:(NSString *)one another:(NSString *)another { forExample = one; anotherExample = another; } - (void)print{ NSLog(@"One = %@, another = %@", forExample, anotherExample); } @end 

Prueba:

 - (void)testClass { SomeClass * s1 = [SomeClass new]; [s1 set:@"one one" another:@"one another"]; SomeClass *s2 = [SomeClass new]; [s2 set:@"two one" another:@"two another"]; [s1 print]; [s2 print]; } 

Y la salida es,

 One = one one, another = two another One = two one, another = two another 

Para que quede claro, nunca declare un IBOutlet como var global (en la implementación) si lo está utilizando para nibs / xibs localizados.

Pasé unas horas pensando por qué la salida solo se puede conectar en una de las puntas localizadas en un momento dado.

Gracias por esta pregunta y las respuestas!

Use un fragmento de código para diferenciar entre una variable miembro y una variable global:

 @implementation MyClass { // It is an ivar, or called member variable // Can NOT be initialized when defined. // Can be accessed with `self->_i` int _i; } - (instancetype)init { if (self = [super init]) { _i = 2; // should be initialized before being used. } return self; } int i = 9; // Global variable, and can be initialized when defined. - (void)myFun { NSLog(@"%i, %i", self->_i, i); } @end // Another file extern int i; NSLog(@"%i", i);