Variabile di class definita in @implementation piuttosto che @interface?

Sono nuovo di Objective-C, ma sono curioso di qualcosa che non ho visto in nessun altro posto.

Qualcuno potrebbe dirmi qual è la differenza tra una variabile privata dichiarata nel blocco @interface rispetto a una variabile dichiarata all’interno del blocco @implementation al di fuori dei metodi della class, ovvero:

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

vs.

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

Sembra che entrambe le variabili (per forExample , un altro anotherExample ) siano ugualmente accessibili in tutta la class e non riesco a trovare una differenza nel loro comportamento. Il secondo modulo è anche chiamato una variabile di istanza?

Quest’ultimo non sta definendo una variabile di istanza. Piuttosto, sta definendo una variabile globale nel file .m. Tale variabile non è univoca o parte di alcuna istanza di object.

Tali globals hanno i loro usi (membri statici C ++ approssimativamente equivalenti, ad esempio la memorizzazione di un’istanza singleton), ma normalmente le definiresti all’inizio del file prima della direttiva @implementation.

Sono molto diversi! Quello in @implementation è una variabile globale non unica per ogni istanza. Immagina che ci fossero degli accessor per entrambe le variabili, scritte in modo ovvio. Quindi la differenza di comportamento è mostrata qui:

 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. 

Se stai cercando questo tipo di comportamento, potresti stare meglio usando una variabile di class, come questa:

 static NSString* yetAnotherExample = nil; 

Quindi puoi usare i metodi di class per interagire con la variabile, ed è chiaramente specifico per la class (al contrario di istanza specifica o globale).

Se dichiari una variabile all’interno della sezione @implementation, stai effettivamente creando una variabile globale, visibile ovunque (in ogni metodo della tua applicazione).

Le variabili membro possono essere dichiarate solo nella sezione @interface. Sono accessibili solo nella class stessa.

Il blocco privato dichiarato all’interno del blocco @implementation è @implementation pericoloso, mi sembra, rispetto ad altri concetti OOP, ad esempio Java. Sembra una variabile membro, ma piuttosto statica.

Il programmatore novizio può facilmente ingannarlo. Scrivo un programma di test e mi sorprendo del comportamento.

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

Implementazione:

 #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 

Test:

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

E l’output è,

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

Per essere chiari, mai e poi mai mai dichiarare un IBOutlet come var globale (nell’implementazione) se lo si sta usando per pennini localizzati / xibs.

Ho trascorso alcune ore a capire perché l’uscita sia collegabile solo in uno dei pennini localizzati in un dato momento.

Grazie per questa domanda e le risposte!

Utilizza uno snippet di codice per indicare la differenza tra una variabile membro e una variabile globale:

 @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);