2010-09-27 11 views
15

Sto cercando di capire lo scopo della direttiva synthesize con il nome della proprietà che sovrascrive. Dire che ho un'interfaccia definita come segue:Objective-C sintetizza il nome della proprietà prioritaria

@interface Dummy ... { 
    UILabel *_dummyLabel; 
} 

@property (retain, nonatomic) UILabel *dummyLabel; 

E nel file di implementazione, ho:

@synthesize dummyLabel = _dummyLabel; 

Da quello che ho capito, "dummyLabel" è solo un alias della variabile di istanza " _dummyLabel". C'è qualche differenza tra self._dummyLabel e self.dummyLabel?

risposta

24

Sì. self._dummyLabel non è definito, tuttavia _dummyLabel non lo è.

La sintassi del punto si espande per invocazioni di metodi semplici, quindi non è specifica per le proprietà. Se hai un metodo chiamato -(id)someObject, ad esempio nel caso di object.someObject, sarà come se scrivessi [object someObject];.

self.dummyLabel //works 
self._dummyLabel //does not work 
dummyLabel  //does not work 
_dummyLabel  //works 
[self dummyLabel]; //works 
[self _dummyLabel]; //does not work 
+0

Grazie per la risposta rapida. Hm ... okay, sono [self.dummyLabel setText: @ "..."] e [_dummyLabel setText: @ "..."] facendo il samething? In tal caso, non vedo alcun grande vantaggio nel ridenominare _dummyLabel in dummyLabel. – Thomas

+0

@Thomas, hai capito. –

+1

Il vantaggio di avere un altro nome per ivar rispetto a quello per la proprietà è che si può facilmente vedere nel codice quando si accede a uno o l'altro. –

17

La tua comprensione non è corretta. dummyLabel è il nome della proprietà ed è non un alias per la variabile di istanza - la variabile di istanza è solo denominata _dummyLabel. Così vale quanto segue per un'istanza di Dummy chiamato myObject:

  • [myObject dummyLabel] funziona
  • myObject.dummyLabel funziona
  • [myObject _dummyLabel] fallisce
  • myObject._dummyLabel fallisce
  • myObject->dummyLabel fallisce
  • myObject->_dummyLabel dipende dalla visibilità del ivar (@public, @private, @protected)
  • [myObject valueForKey: @"dummyLabel"] fabbrica
  • [myObject valueForKey: @"_dummyLabel"] dipende dall'implementazione di +accessInstanceVariablesDirectly (cioè funzionerà nel caso predefinito in cui +accessInstanceVariablesDirectly restituisce YES).
+0

Quindi, quando voglio accedere a una variabile di istanza all'interno di un metodo, potrei usare '_dummyLabel = @" blah "' - e questo cambierebbe il valore direttamente, piuttosto che passare attraverso un setter? Quindi potrei avere una proprietà di sola lettura senza setter, ma cambiarla internamente andando direttamente a Ivar? E se voglio usare un getter/setter all'interno di un metodo della classe, userò semplicemente "self.dummyLabel"? Oppure potrei usare anche 'dummyLabel' direttamente? –

0

non vedo alcuna grande vantaggio di rinominare _dummyLabel a dummyLabel

In alcuni objC tempi di esecuzione si ha difficoltà a fare le variabili di istanza invisibile agli utenti della classe. Per loro l'inserimento di un prefisso (o suffisso) sulle variabili di istanza può chiarire (o più chiaramente) che non si vuole che nessuno faccia scherzi con le variabili. Comunque non vuoi quella gunk sulle tue funzioni pubbliche. Questo ti permette di farcela.

Potrebbe anche essere utile se è necessario mantenere una vecchia interfaccia con un set di nomi contemporaneamente a un nuovo set di API con un nuovo set di nomi (setLastname vs. setSurname).

13

Il vantaggio di avere un altro nome per l'Ivar rispetto per la proprietà è che si può facilmente vedere nel codice quando si accede a uno o l' altro - Andre K

I Non riesco a trovare un pulsante "comment", quindi devo pubblicare una "risposta".

Volevo solo ampliare il commento di Andre - sapendo quando si utilizzano le proprietà sintetizzate rispetto alla variabile vaniglia, si sa (specialmente nel caso di setter) quando una variabile viene mantenuta/copiata/rilasciata automaticamente grazie al proprio setter, contro essere manipolato a mano.

Ovviamente se stai facendo le cose nel modo giusto, probabilmente non hai bisogno dell'aiuto di un setter per conservare/rilasciare correttamente gli oggetti! Ma ci possono essere anche altri scenari in cui il riferimento ai tuoi ivars come self.ivar invece di _ivar può essere utile, ad esempio quando si utilizzano setter/getter personalizzati al posto di quelli sintetizzati di default. Forse ogni volta che modifichi una proprietà, vuoi anche memorizzarla su NSUserDefaults. Quindi, si potrebbe avere qualche codice come questo:

@interface SOUserSettings : NSObject { 

BOOL _autoLoginOn; 

} 

@property (nonatomic, assign) BOOL autoLoginOn; 

@end 

@implementation SOUserSettings 

@synthesize autoLoginOn = _autoLoginOn; 

- (void)setAutoLoginOn:(BOOL)newAutoLoginOnValue { 

    _autoLoginOn = newAutoLoginOnValue; 
    [[NSUserDefaults standardUserDefaults] setBool:_autoLoginOn forKey:@"UserPrefAutoLoginOn"]; 
} 

@end 

Nota: Questo è solo il codice illustrativo, ci potrebbero essere mille cose che non va!

Quindi, nel codice, se si dispone di una riga che dice _autoLoginOn = YES - si sa che non verrà salvato in NSUserDefaults, mentre se si utilizza self.autoLoginOn = YES si sa esattamente cosa sta per accadere.

La differenza tra _autoLoginOn e self.autoLoginOn è più che semantica.

+0

Eccellente, che tu l'abbia menzionato! C'è davvero una differenza! –

0

Vecchio post, ma penso sia importante ricordare che si consiglia di accedere alle variabili tramite getter e setter (quindi, con notazione punto). L'accesso diretto a un campo (_ivar) è fortemente raccomandato solo durante l'inizializzazione.

C'è qualche buon articolo di Apple: https://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html

Ultimo paragrafo:

Si dovrebbe sempre accedere alle variabili di istanza direttamente dall'interno un metodo di inizializzazione perché al momento di una proprietà è impostata, il il resto dell'oggetto potrebbe non essere ancora completamente inizializzato. Anche se si non si forniscono metodi di accesso personalizzati o si conosce alcun effetto collaterale da all'interno della propria classe, una sottoclasse futura potrebbe sovrascrivere il comportamento .

Problemi correlati