Come funziona una sottolineatura di fronte a una variabile in un lavoro di c-class objective-c?

Ho visto in alcuni esempi di iPhone che gli attributi hanno usato un trattino basso _ davanti alla variabile. Qualcuno sa cosa significa? O come funziona?

Un file di interfaccia che sto usando assomiglia a:

@interface MissionCell : UITableViewCell { Mission *_mission; UILabel *_missionName; } @property (nonatomic, retain) UILabel *missionName; - (Mission *)mission; 

Non sono sicuro di cosa faccia esattamente quanto sopra, ma quando provo a impostare il nome della missione come:

 aMission.missionName = missionName; 

Ottengo l’errore:

richiesta per membro ‘missionName’ in qualcosa che non sia una struttura o unione

Se si utilizza il prefisso di sottolineatura per i propri ivars (che non è altro che una convenzione comune, ma utile), allora è necessario fare 1 cosa in più in modo che l’accessore generato automaticamente (per la proprietà) sappia quale ivar usare. In particolare, nel tuo file di implementazione, il tuo synthesize dovrebbe assomigliare a questo:

 @synthesize missionName = _missionName; 

Più genericamente, questo è:

 @synthesize propertyName = _ivarName; 

È solo una convenzione per la leggibilità, non fa nulla di speciale per il compilatore. Vedrai che le persone lo usano su variabili di istanza private e nomi di metodi. Apple consiglia di non utilizzare il carattere di sottolineatura (se non stai attento, potresti ignorare qualcosa nella tua superclass), ma non dovresti sentirti male ignorando quel consiglio. 🙂

L’unico scopo utile che ho visto è di distinguere tra variabili locali e variabili membro come sopra indicato, ma non è una convenzione necessaria. Quando associato a una proprietà @, aumenta la verbosità delle istruzioni di sintesi – @synthesize missionName = _missionName; ed è brutto ovunque

Invece di usare il carattere di sottolineatura, basta usare nomi di variabili descrittive all’interno di metodi che non siano in conflitto. Quando devono entrare in conflitto, il nome della variabile all’interno del metodo dovrebbe subire un carattere di sottolineatura, non la variabile membro che può essere utilizzata da più metodi . L’unico posto comune è utile in un setter o in un metodo init. Inoltre, renderà più sintetica la dichiarazione @synthesize.

 -(void)setMyString:(NSString*)_myString { myString = _myString; } 

Edit: Con l’ultima caratteristica del compilatore di auto-sintesi, ora uso il carattere di sottolineatura per l’ivar (nella rara occasione in cui ho bisogno di usare un ivar per abbinare ciò che fa l’auto-sintesi.

In realtà non significa nulla, è solo una convenzione che alcune persone usano per differenziare le variabili membro dalle variabili locali.

Per quanto riguarda l’errore, sembra che aMission abbia il tipo sbagliato. Quale è la sua dichiarazione?

Questo è solo per la convenzione di denominazione delle proprietà di sintesi.

Quando sintetizzi le variabili nel file .m, Xcode ti fornirà automaticamente un’intelligenza variabile.

Avere un carattere di sottolineatura non solo rende ansible risolvere i tuoi ivar senza ricorrere alla syntax self.member ma rende il tuo codice più leggibile poiché sai quando una variabile è un ivar (a causa del suo prefisso di sottolineatura) o un argomento di membro (nessuna sottolineatura ).

Esempio:

 - (void) displayImage: (UIImage *) image { if (image != nil) { // Display the passed image... [_imageView setImage: image]; } else { // fall back on the default image... [_imageView setImage: _image]; } } 

Questo sembra essere l’elemento “principale” per domande su self.variableName vs. _variablename. Quello che mi ha gettato un cappio era che nel .h, avevo:

 ... @interface myClass : parentClass { className *variableName; // Note lack of _ } @property (strong, nonatomic) className *variableName; ... 

Questo porta a self.variableName e _variableName che sono due variabili distinte nel .m. Quello di cui avevo bisogno era:

 ... @interface myClass : parentClass { className *_variableName; // Note presence of _ } @property (strong, nonatomic) className *variableName; ... 

Quindi, nella class ‘.m, self.variableName e _variableName sono equivalenti.

Quello su cui non sono ancora chiaro è il motivo per cui molti esempi funzionano ancora, anche se ciò non è ansible.

raggio

invece di underscore puoi usare il nome self.variable o puoi sintetizzare la variabile per usare la variabile o l’outlet senza underscore.

Manca dalle altre risposte che l’uso di _variable ti impedisce di digitare in modo assente la variable e di accedere a ivar piuttosto che alla proprietà (presumibilmente intesa).

Il compilatore ti costringerà ad usare sia self.variable che _variable . L’utilizzo dei caratteri di sottolineatura rende imansible digitare la variable , il che riduce gli errori del programmatore.

 - (void)fooMethod { // ERROR - "Use of undeclared identifier 'foo', did you mean '_foo'?" foo = @1; // So instead you must specifically choose to use the property or the ivar: // Property self.foo = @1; // Ivar _foo = @1; }