Objective-C sintetizzare nome della proprietà assoluta
-
25-09-2019 - |
Domanda
Sto cercando di capire lo scopo della direttiva synthesize
con il nome di proprietà prevalente. Dire che ho un'interfaccia definita come segue:
@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?
Soluzione
Sì. self._dummyLabel
non è definito, ma non è _dummyLabel
.
sintassi Dot si espande fuori per semplici chiamate di metodo, quindi non è specifico per le proprietà. Se si dispone di un metodo chiamato -(id)someObject
, ad esempio nel caso di object.someObject
, sarà come se hai scritto [object someObject];
.
self.dummyLabel //works
self._dummyLabel //does not work
dummyLabel //does not work
_dummyLabel //works
[self dummyLabel]; //works
[self _dummyLabel]; //does not work
Altri suggerimenti
La vostra comprensione è corretta. dummyLabel
è il nome della proprietà, ed è non un alias per la variabile di istanza - la variabile di istanza è solo chiamato _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"]
funziona -
[myObject valueForKey: @"_dummyLabel"]
dipende l'attuazione di+accessInstanceVariablesDirectly
(vale a dire che funzionerà nel caso di default in cui i rendimenti+accessInstanceVariablesDirectly
YES
).
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' altre - Andre K
Non sono in grado di trovare un pulsante 'commento' così sto dover inserire come 'risposta'.
Volevo solo per espandere il commento di Andre - sapendo quando si utilizza le proprietà sintetizzati vs la variabile di vaniglia, si sa (soprattutto in caso di setter) quando una variabile viene mantenuta / copia / rilasciati automaticamente grazie al vostro bel setter , vs essere manipolato a mano.
Naturalmente se si sta facendo le cose per bene, probabilmente non è necessario l'aiuto di un setter di mantenere / release oggetti correttamente! Ma ci possono essere altri scenari in cui anche riferendosi ai vostri Ivars come self.ivar
invece di _ivar
può essere utile, ad esempio quando si utilizza setter custom / getter al posto di quelli di default sintetizzato. Forse ogni volta che si modifica una proprietà, si vuole anche per memorizzare a NSUserDefaults. Così 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 potrebbe essere un torto mille cose con esso
Così ora, nel codice, se si dispone di una linea che dice _autoLoginOn = YES
-. Sai che non sta per essere salvato NSUserDefaults, mentre se si utilizza self.autoLoginOn = YES
si sa esattamente cosa sta per accadere
La differenza tra _autoLoginOn
e self.autoLoginOn
non è solo semantica.
Non vedo alcuna grande vantaggio di ridenominazione _dummyLabel a dummyLabel
In alcuni objC tempi di esecuzione si dispone di un disco variabili di istanza rendendo il tempo invisibile agli utenti della classe. Per attaccarle qualche prefisso (o suffisso) sulle variabili di istanza può mettere in chiaro (o più chiaro) che non vuoi che nessuno scherzi con le variabili. Tuttavia non si vuole che gunk sulle vostre funzioni pubbliche. Ciò consente di farlo fuori.
Potrebbe anche essere utile se avete bisogno di mantenere una vecchia interfaccia con una serie di nomi, allo stesso tempo come un nuovo set di API con una nuova serie di nomi (setLastname vs. setSurname).
Old post, ma penso che la sua importante ricordare, che si consiglia di variabili di accesso tramite getter e setter (così, con la notazione del punto). Accedendo direttamente un campo (_ivar) è fortemente raccomandato solo quando l'inizializzazione di esso.
C'è qualche buon articolo di Apple: https://developer.apple.com/ biblioteca / ios / # documentazione / cacao / concettuale / ProgrammingWithObjectiveC / EncapsulatingData / EncapsulatingData.html
Ultimo paragrafo:
Si dovrebbe sempre accedere alle variabili di istanza direttamente dall'interno un metodo di inizializzazione perché al momento una proprietà è impostata, la resto dell'oggetto non può ancora essere completamente inizializzato. Anche se tu non forniscono personalizzati metodi di accesso o di sapere di eventuali effetti collaterali da all'interno la propria classe, un futuro sottoclasse può benissimo ignorare il comportamento.