2010-08-16 8 views
13

Ho cercato molte domande su accessors ObjC e accessors sintetizzati inutilmente. Questa domanda è più di una domanda "aiutami a risolvere un problema"; Non mi aspetto una risposta, ma sono piuttosto alla ricerca di esperti che valutino l'argomento.In Objective-C su iOS, qual è la differenza (stile) tra "self.foo" e "foo" quando si usano getter sintetizzati?

In una classe Cocoa Touch, vorrei scrivere qualche codice come questo (dove soundEffects è una struttura NSArray sintetizzata):

id foo = [self.soundEffects objectAtIndex:1]; 

Un collega mi ha chiesto di spiegare il motivo per cui quanto sopra è meglio di questa linea:

id foo = [soundEffects objectAtIndex:1]; 

Bene, funzionalmente, non è diverso.

mie argomentazioni per l'ex sono come segue:

  1. self.soundEffects dice ogni altro coder lavorare sul codice che si tratta di un iVar, non una variabile ambito locale.

  2. Se fosse necessario, potremmo inserire la logica personalizzata nell'accessorio getter soundEffects.

  3. Per nessun motivo concreto, "sembra" la cosa giusta da fare dopo aver lavorato in Obj-C per un anno.

accetta argomenti # 1 e # 2 come valido, ma dà anche il contrappunto:

  1. Non è questo solo codice di pesantezza?

  2. Non si dovrebbe consentire a una classe di parlare direttamente con i propri iVars senza dover chiamare un metodo (il getter) su se stesso?

Chi prende?

+2

I penso che self.soundEffects sia migliore perché altri oggetti possono sapere quando il valore cambia attraverso la codifica del valore-chiave, ma altrimenti non sanno che è cambiato ... –

+0

Vuoi dire valore-chiave _observing_, b Ciò non avrebbe comunque effetto qui, @ Tom. '[self.myMutableArray addObject: anObject]' non notifica gli osservatori; solo 'setMyMutableArray:' fa. –

+0

Ah sì, hai ragione su entrambi i fronti. Ma credo che sia passato un po 'di tempo! Il punto indica ancora alcuni usi in cui questa domanda potrebbe apparire, anche se non pertinente per l'esempio che ha usato. –

risposta

5

tuo punto 1 non è giusto: è self.soundEffectsnon un Ivar, anche se può capitare di darvi qualcosa che è - come avviene nel caso del vostro sintetizzato NSArray, al momento .

Questo a sua volta implica che il punto 2 è il nocciolo della questione: se instradi tutti gli accessi tramite l'accessor, allora tutto è ben incapsulato e sei libero di modificare l'implementazione in seguito senza dovermi preoccupare del lato effetti.

È anche una buona pratica quando si utilizza il mutatore, in modo da mantenere una gestione coerente della memoria.

Per la maggior parte, io direi che è consigliabile percorso attraverso self.property per tutto ciò che è una proprietà, e limitare l'accesso Ivar diretto alle cose che sono strettamente interno. Tuttavia, ammetto che in alcuni casi, specialmente per le cose che non usano la semantica retain/copy, può essere più una preferenza di stile.

+1

"Strettamente interno" è il problema. Quando si utilizza un getter all'interno della stessa classe, alcuni possono sostenere che una classe ha bisogno di conoscere la propria implementazione. Un fan di programmazione funzionale, preferisco tenerlo ancora più stretto di quello (i metodi sono quanto più autosufficienti possibile), quindi è per questo che preferisco la sintassi self. – makdad

4

utilizzando qualcosa come self.variable = nil fa passare la variabile attraverso il suo setter e quindi ottiene la memoria gestita gratuitamente. se si usa semplicemente variable = nil per esempio in un metodo dealloc, causerà una perdita poiché non sta effettivamente passando attraverso il setter sintetizzato per la variabile e diminuendo il conteggio dei ritiri. Vedi questo post memory leak with self.

Per questo motivo, è consigliabile (credo) utilizzare sempre l'auto. quando si tratta di variabili di istanza possedute per quanto riguarda la gestione della memoria.

+0

Grazie. Siamo perfettamente convinti dell'utilizzo di self.property = nil anziché solo property = nil. Quello che mi interessa di più è il lato positivo delle cose. qualche idea? – makdad

+0

In realtà si ritiene che sia meglio rilasciare le variabili di istanza direttamente in dealloc anziché utilizzare le proprietà di accesso. –

+0

Luke- vorrebbe sapere perché. Qualche idea? – makdad

9

Personalmente ho scelto di utilizzare un prefisso di sottolineatura per Ivars, e questo tipo di sintetizzare

@synthesize name = _name; 

In questo modo non li mischiare.Il problema principale con non utilizzando sé è che questo codice

_name = ... 

è molto diverso da

self.name = ... 

Quando il @property utilizza l'opzione conservare. Il primo non mantiene l'oggetto e il secondo chiama il setter sintetizzato che conserva.

L'unica volta che fa una grande differenza è con l'assegnazione, quindi tendo a usare sempre self. quindi mi assicuro di farlo sugli assegnamenti.

+3

Fai attenzione se stai usando quel trattino basso con framework Cocoa. Apple riserva l'uso del trattino di sottolineatura principale per iVar di classe e potresti incontrare difficoltà nel selezionare un nome identico per un iVar di una sottoclasse. – ohhorob

+1

+1 È * molto * importante riconoscere che quando si assegnano le proprietà, retain non viene chiamato senza usare il "self". sintassi. – meddlingwithfire

+0

@meddlingwithfire Sono nuovo di Obj-C ma voi ragazzi siete seri ... 'propertyName' è funzionalmente diverso da' self.propertyName'? Anche nel moderno Obj-C? Questo fa solo un sacco di problemi ... – devios1

1

self.soundEffects
imposta/ottiene la variabile di istanza tramite il setter/getter, e quindi se vogliamo fare alcune operazioni personalizzate quando il loro valore cambia, quella logica può andare nel loro getter/setter.

anche come per iOS 6, l'ivar corrispondente a

@property (nonatomic)NSArray *propertyName;

sarà

_propertyName

quindi credo che non puoi utilizzare

id foo = [soundEffects objectAtIndex:1];
anymore.Not sicuro though.Instead si dovrebbe usare
id foo = soundEffects[1];