In Objective-C su iOS, qual è la differenza (stile) tra “self.foo” e “foo” quando si utilizzano getter sintetizzati?

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 una class Cocoa Touch, scriverei un codice come questo (dove soundEffects è una proprietà NSArray sintetizzata):

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

Un collega mi ha chiesto di spiegare perché quanto sopra è meglio di questa linea:

 id foo = [soundEffects objectAtIndex:1]; 

Beh, funzionalmente, non è diverso.

I miei argomenti per il primo sono i seguenti:

  1. self.soundEffects dice a ogni altro codificatore che lavora sul codice che questo è un iVar, non una variabile con ambito locale.

  2. Se mai avessimo bisogno di, potremmo mettere la logica personalizzata nel soundEffects accessor getter.

  3. Per nessuna ragione concreta, “sente” come la cosa giusta da fare dopo aver lavorato in Obj-C per un anno.

Accetta gli argomenti n. 1 e n. 2 come validi, ma dà anche il contrappunto:

  1. Non è solo questo codice gonfio?

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

Qualche acquirente?

Il tuo punto 1 non è corretto: self.soundEffects non è un ivar, anche se può capitare di darti qualcosa che è – come nel caso del tuo NSArray sintetizzato, al momento .

Questo a sua volta implica che il tuo 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 un secondo momento senza doversi preoccupare degli effetti collaterali.

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

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

Ho deciso personalmente di utilizzare un prefisso di sottolineatura per ivars e questo tipo di sintetizzare

 @synthesize name = _name; 

In questo modo non li mescolo. Il problema principale di non usare se stessi è questo codice

 _name = ... 

è molto diverso da

 self.name = ... 

Quando @property utilizza l’opzione di conservazione. Il primo non mantiene l’object e il secondo chiama il setter sintetizzato che conserva.

L’unica volta che fa una grande differenza è con l’assegnazione, quindi tendo a usare me self. tutto il tempo quindi mi assicuro di farlo su assegnazioni.

usando qualcosa come self.variable = nil fa in modo che la variabile passi attraverso il suo setter e quindi ottiene la memoria gestita gratuitamente. se si usa solo variable = nil ad 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 messaggio di perdita di memoria con sé.

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

  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 ios 6, l’ivar corrispondente a

  @property (nonatomic) NSArray * propertyName; 

sarà

  _nome della proprietà 

quindi credo che non puoi usare

  id foo = [soundEffects objectAtIndex: 1]; 

più.Non certo però.Invece dovresti usare

  id foo = soundEffects [1];