¿Variables de instancia de Objective-C?

Resuelto Dwayne King asked hace 11 años • 4 respuestas

Estoy seguro de que mi confusión aquí es solo el resultado de estar atrapado en una "mentalidad Java" y no entender en qué se diferencia Obj-C en este caso.

En Java, puedo declarar una variable en una clase, como esta, y cada instancia de esa clase tendrá la suya propia:

MyClass {

  String myVar;

  MyClass() {
    // constructor
  }
}

En Obj-C intenté hacer lo mismo declarando una variable solo en el archivo .m así:

#import "MyClass.h"

@implementation MyClass

NSString *testVar;

@end

Mi expectativa aquí era que esta variable tuviera un alcance limitado a esta clase. Entonces creé una segunda clase (idéntica):

#import "MySecondClass.h"

@implementation MySecondClass

NSString *testVar;

@end

Lo que estoy viendo (y me tiene desconcertado) es que cambiar la variable en una clase afecta el valor visto en la otra clase. De hecho, si establezco un punto de interrupción y luego "Salto a la definición" de la variable, me lleva al

He creado un proyecto Xcode extremadamente pequeño que demuestra el problema aquí .

Dwayne King avatar Nov 07 '12 11:11 Dwayne King
Aceptado

Cambia esto:

@implementation MyClass

NSString *testVar;

@end

a:

@implementation MyClass {
    NSString *testVar;
}

// methods go here

@end

y obtendrás lo que esperabas.

Tal como lo tenías, en realidad estás creando una variable global. El vinculador combinó las dos variables globales en una, por lo que ambas cambiaron cuando configuró una. La variable entre llaves será una variable de instancia adecuada (y privada).

Editar: Después de recibir un voto negativo sin razón aparente, pensé en señalar la forma "antigua" de hacer las cosas y la nueva.

A la antigua usanza:

algunaclase.h

@interface SomeClass : UIViewController <UITextFieldDelegate> {
    UITextField *_textField;
    BOOL _someBool;
}

@property (nonatomic, assign) BOOL someBool;

// a few method declarations

@end

algunaclase.m

@implementation SomeClass

@synthesize someBool = _someBool;

// the method implementations

@end

Ahora la forma nueva y mejorada con el compilador moderno Objective-C:

algunaclase.h

@interface SomeClass : UIViewController

@property (nonatomic, assign) BOOL someBool;

// a few method declarations

@end

algunaclase.m

@interface SomeClass () <UITextFieldDelegate>
@end

@implementation SomeClass {
    UITextField *_textField;
}

// the method implementations

@end

La nueva forma tiene varias ventajas. La principal ventaja es que ninguno de los detalles específicos de la implementación sobre la clase aparece en el archivo .h. Un cliente no necesita saber qué delega las necesidades de implementación. El cliente no necesita saber qué ivars uso. Ahora, si la implementación necesita un nuevo ivar o necesita usar un nuevo protocolo, el archivo .h no cambia. Esto significa que se vuelve a compilar menos código. Es más limpio y mucho más eficiente. También facilita la edición. Cuando estoy editando el archivo .m y me doy cuenta de que necesito un nuevo ivar, hago el cambio en el mismo archivo .m que ya estoy editando. No es necesario cambiar de un lado a otro.

También tenga en cuenta que la implementación ya no necesita un ivar o @synthesizepara la propiedad.

rmaddy avatar Nov 07 '2012 04:11 rmaddy