2013-01-01 6 views
7

Eventuali duplicati:
How does an underscore in front of a variable in a cocoa objective-c class work?self.variableName vs _variableName vs @sysnthesize nomeVariabile


Nota: per la gente scavare intorno cercando di capire questo, io capito la fonte della mia confusione. Nel .h, avevo:

... 
@interface myClass : parentClass { 
className *variableName: 
} 

@property (strong, nonatomic) className *variableName; 
... 

Questo porta a self.variableName e _variableName essendo due variabili distinte nel .m. Mi serviva:

... 
@interface myClass : parentClass { 
className *_variableName: 
} 

@property (strong, nonatomic) className *variableName; 
... 

Poi, nel .m class', self.variableName e _variableName sono equivalenti


Nel nuovo di zecca, Xcode 4.5+, con ARC, il targeting iOS 5.0 + progetto, c'è un netto vantaggio (efficienza di runtime, velocità, ecc.) nell'uso di _variableName su self.variableName rispetto al vecchio stile @synthesize variableName?

mia comprensione è che Xcode 4.5+ creerà una funzione di accesso di default _variableName che è equivalente a self.variableName e gli unici motivi per non usare @synthesize variableName è quello di evitare confusione tra Ivars e passato-in variabili, giusto?

Per me, usare solo self.variableName per accedere a un iVar sembra il più diretto e chiaro su quale variabile si sta cercando. Oltre alla digitazione di _ rispetto a self., c'è un vantaggio nell'utilizzo di _variableName?

+1

Ed ecco un altro 16: http://stackoverflow.com/q/5582448/ http://stackoverflow.com/q/6049269/ http://stackoverflow.com/q/2371489/ http://stackoverflow.com/q/7174277/ http://stackoverflow.com/q/5659156 http://stackoverflow.com/q/837559/ http://stackoverflow.com/q/6146244/ http: // StackOverflow.it/q/10651535/ http://stackoverflow.com/q/6124109/ http://stackoverflow.com/q/8145373/ http://stackoverflow.com/q/3521254/ http: // stackoverflow.com/q/6064283/ http://stackoverflow.com/q/9696359/ http://stackoverflow.com/q/5521499/ http://stackoverflow.com/q/5466496/ http: //stackoverflow.com/q/2114587/ –

+0

Il mio male. Non penso di cercare 'underscore' enunciati. Detto questo, verificando alcuni dei potenziali duplicati, non ho visto alcuna menzione a prova di novizio dei potenziali problemi con l'osservazione dei valori-chiave, i collegamenti e l'accesso sicuro ai thread (atomico) se _variableName è usato contro self .variableName. Uno (4088801) ha menzionato un potenziale problema se l'oggetto cui si fa riferimento in _variableName è condiviso e consigliato utilizzando invece self.variableName. –

+0

Se vedi un problema specifico trascurato in una delle molte istanze della domanda generale, dovresti certamente sentirti libero di chiedere informazioni dettagliate. Tuttavia, non ha molto valore avere queste informazioni nascoste in un'altra copia. –

risposta

15

mia comprensione è che Xcode 4.5+ creerà una funzione di accesso di default "_variableName" che equivale a self.variableName e le uniche ragioni per non usare "@synthesize nomeVariabile" è quello di evitare confusione tra Ivars e passato-in variabili, corretto?

In questo caso, non è _variableName la funzione di accesso, è un ivar che viene generato automaticamente dal compilatore e utilizzato nei setter e getter @synthesized automaticamente. Generalmente, è preferibile utilizzare accessors ogni volta che è possibile (ad esempio, self.variableName) in modo che le cose come l'osservazione del valore chiave e le associazioni funzionino per quella proprietà.

Quando si accede direttamente a un ivar, si accede tramite accesso diretto alla memoria, allo stesso modo in cui si accede ai dati in una struttura. Prende semplicemente il puntatore dell'oggetto che possiede l'ivar, sposta l'indirizzo di memoria e tenta di leggere o scrivere nella memoria in quella posizione. Usando la notazione punto (self.variableName) chiama il metodi di accesso per impostare o ottenere che la proprietà e può fare un certo numero di cose diverse lungo il percorso, come ad esempio:

1) Blocco: se la proprietà sta per essere utilizzato in più thread ed è una proprietà atomic, il runtime eseguirà automaticamente alcuni blocchi per assicurarsi che la proprietà non sia accessibile contemporaneamente da più thread. Se il tuo oggetto non è pensato per essere usato su più thread, puoi dare l'hint nonatomic nella dichiarazione della tua proprietà in modo che gli accessori sintetizzati saltino il blocco.

2) valore-chiave delle Notifiche: il setter di default per le proprietà chiamano -willChangeValueForKey: e -didChangeValueForKey:, che invia le notifiche quando la proprietà è cambiata. Ciò è necessario affinché qualsiasi cosa si aggiorni correttamente se vengono utilizzati i binding e per qualsiasi altra osservazione del valore-chiave.

3) Comportamento di accesso personalizzato: Se si finisce per scrivere i propri setter e getter, qualsiasi materiale personalizzato implementato in essi.

Tecnicamente, l'accesso diretto a ivar è più rapido rispetto all'utilizzo degli accessor, ma ci sono pochissime situazioni in cui si verificheranno notevoli differenze di prestazioni e probabilmente si tratterà di un'ottimizzazione prematura. Anche se non hai voglia di usare i vantaggi elencati sopra, è probabilmente meglio usare comunque gli accessor in modo che se decidi in seguito di averne bisogno, non devi cambiare ogni istanza di accedere a quella variabile (e possibilmente creare nuovi bug inaspettati nel processo).

Inoltre, se si accede direttamente a ivars e si termina il refactoring della classe in categorie o sottoclassi, diventa difficile poiché in genere si deve dichiarare ivar come variabile @protected. Non dovresti farlo se stai usando gli accessori.

In genere, provo ad accedere solo agli ivars direttamente in init, dealloc e all'accessorio della proprietà. Molti ingegneri seguono questa regola empirica, perché a volte le cose personali che avvengono negli accessor possono causare comportamenti imprevisti mentre l'oggetto è init o dealloc. Ad esempio, se qualcosa nei metodi di accesso causa qualcosa a retain o release il proprio oggetto o addirittura forma un riferimento debole di azzeramento ad esso, causerà un arresto anomalo se utilizzato in dealloc.

5

Nell'ultimo Xcode @synthesize è facoltativo. Per default, omettendo @synthesize è la stessa scrittura

@synthesize someName = _someName; 

L'unica ragione per usare @synthesize è quello rinominare variabile istanza creata per memorizzare il valore della proprietà, per esempio

@synthesize someName = someSpecialName; 

Quando si utilizza self.variableName per accedere a una variabile, si passa attraverso una proprietà, che è un metodo breve che accede alla variabile di istanza per conto dell'utente. Sebbene la spedizione del metodo sia molto veloce, può eseguire per te ulteriori servizi, come la sincronizzazione dell'accesso alla variabile (questo è il caso quando si specifica atomic o non si specifica nonatomic nella dichiarazione di proprietà). In casi come questo, l'accesso tramite self.variableName sarà un po 'più lento. Se fatto in un circuito chiuso, questo potrebbe potenzialmente fare la differenza. Questo è il motivo per cui a volte si desidera accedere direttamente alla variabile di istanza sottostante utilizzando _variableName.

+0

Solo per essere pedante, basato sulla tua risposta e @eyebrowsoffire, _variableName, potrebbe essere più veloce, ma self.variableName è più sicuro? –

+0

@RayatERISCorp "Più sicuro" è sottodimensionato in questo contesto, ma se la tua intenzione era quella di usare una proprietà in modo sincronizzato (cioè è "atomico") la risposta è sì, è più sicura. In effetti, l'altro modo (cioè andare direttamente in "_variableName') semplicemente non funziona senza un ulteriore blocco. – dasblinkenlight

+0

Gotcha. Con "più sicuro" intendo "meno probabilità di attivare qualche bug inaspettato nel mio codice che mi lascerà il debugging per molto più tempo di quanto avrei dovuto, perché l'uso di _variableName non comporta automaticamente il kick-off di alcune azioni eseguite da self.variableName." –

Problemi correlati