Domanda

Qual è la sintassi corretta per l'accesso a una variabile di istanza in Objective-C?

Supponiamo di avere questa variabile:

@interface thisInterface : UIViewController {
    NSMutableString *aString;
}

@property (nonatomic, retain) NSMutableString *aString;

e che è sintetizzato.

Quando vogliamo accedervi, prima vorremmo allocarlo e inizializzarlo. Avendo programmato in Objective-C per circa un mese, ho visto due diverse forme di sintassi. Ho visto le persone fare semplicemente aString = [[NSMutableString alloc] initWithString:@"hi"], dove allocano la stringa in quel modo; Ho anche visto le persone iniziare con self.aString E poi procedono a inizializzare il loro Ivar. Immagino che sto solo cercando di capire qual è il modo più corretto di inizializzare una variabile di istanza, perché con il primo esempio, ho ricevuto errori Exc_bad_access da esso. Dopo aver preparato il self. Tuttavia, non è apparso.

Perdonami se questa è una domanda duplicata, ma dopo aver letto alcuni post su così, mi ha reso curioso. Sto cercando di imparare la sintassi corretta con Objective-C perché preferisco essere corretto piuttosto che sciatto.

È stato utile?

Soluzione

Se hai dichiarato una proprietà e @synthesize It nel file .m, lo hai semplicemente impostato in questo modo:

self.aString = @"hi"; // or [[NSMutableString alloc] initWithString:@"hi"];

Usando self.varName sfrutta ciò che la tua dichiarazione di proprietà effettivamente fa, gestisce la conservazione del nuovo valore (poiché la tua proprietà ha il retain attributo), rilasciando il vecchio valore, ecc. Per te.

Se fai solo:

aString = someValue;

... Potresti perdere il valore originale che si trovava aString, poiché senza usare self.aString Stai accedendo alla variabile direttamente contro la proprietà.

Altri suggerimenti

Notare la differenza tra self->varName e self.varName

Il primo è Pointer accesso. Il secondo è proprietà accesso.

Perché è importante? L'accesso al puntatore è diretto. Accesso alla proprietà, d'altra parte si avvale di getter e setter (siano essi loro @synthesized o no). Inoltre, per comodità, gli accessori @Syntesized si prendono cura del manager per te (cioè quando si utilizzano self.varName = ...;), invece varName = ...; Fa solo quello che dice, cioè l'incarico -> (c'è la spiegazione degli errori Exc_bad_access che potresti ottenere).

Sintatticamente, entrambe le forme sono corrette. Se vuoi comunicare meglio l'intento, usa self->varName Quando vuoi lavorare direttamente con il puntatore e utilizzare self.varName Quando vuoi approfittare del @property convenienza.

Ecco tutte le possibili combinazioni (penso) ok e cattivi sono corretti solo quando aString la proprietà ha retain attributo:

@property (nonatomic, retain) NSMutableString *aString;

Così:

1

aString = [[NSMutableString alloc] init]; //OK: 

Questo va bene, ma solo nel caso che la astruttura non punta a un oggetto non valido o perderai un riferimento a quell'oggetto e perde perché non sarai in grado di raggiungerlo per rilasciarlo.

2

aString = [NSMutableString string]; //BAD

Cattivo perché si suppone di trattenere l'astring (come l'hai dichiarato in quel modo), non lo stai mantenendo e otterrai sicuramente EXC_BAD_ACCESS in futuro

3

aString = [[NSMutableString string] retain]; //OK

Come il primo approccio, solo buono se Astring non indica un oggetto valido. Tuttavia, però userò il primo.

4

aString = [[[NSMutableString alloc] init] autorelease];//BAD

Come il secondo approccio.

5

self.aString = [[NSMutableString alloc] init]; //BAD!!

Cattivo perché lo stai mantenendo due volte, quindi porterà a perdite di memoria

6

self.aString = [[NSMutableString string]; //******GOOD!******

Questo è probabilmente il più sicuro. Sarà mantenuto dal setter di proprietà e poiché si utilizza il setter qualsiasi altro oggetto che avrebbe potuto essere indicato da astring verrà rilasciato in modo appropriato

7

self.aString = [[NSMutableString string] retain]; //BAD

Questo è mantenuto due volte.

8

self.aString = [[[NSMutableString alloc] init] autorelease];//Ok

Anche questo va bene, ma userei il metodo di convenienza invece di questo lungo approccio :)

Diffidati che le opzioni n. 1 e #3 siano perfettamente buone se sai cosa stai facendo. In effetti li uso molto più frequentemente di #6

Personalmente preferisco usare il self. sintassi. Rende solo più facile determinare che è una variabile di istanza e non solo un'altra variabile nell'ambito attuale che andrà persa quando il suo NSAutouterleeSepool è drenato. Tuttavia, è corretto usarli in entrambi i modi e se stai ricevendo errori EXC_BAD_ACCESS, non è perché hai acceduto senza usare self.. Hai ragione nel dire che devi alloc e in qualsiasi modo tu scelga di accedere alle tue variabili, mantenerlo coerente o riceverai errori.

Spero che questo aiuti.

Usa sempre gli accessori tranne in init, dealloc e negli accessori stessi. In questo modo ti farà risparmiare un sacco di mal di testa come quello che stai descrivendo. Inoltre, nomina i tuoi Ivars qualcosa di diverso dalla tua proprietà (_foo, foo_, mFoo, ma no foo).

self.foo è esattamente lo stesso di [self foo]. Chiama il metodo foo. self.foo = x è esattamente lo stesso a [self setFoo:x]. Chiama il metodo setFoo:. Se hai sintetizzato la proprietà foo come un retain variabile, quindi questo sembra qualcosa di simile:

@synthesize foo = foo_;

- (void)setFoo:(id)value {
  [value retain];
  [foo_ release];
  foo_ = value;
}

Questo rilascia correttamente il vecchio valore di foo_, ne assegna uno nuovo e lo conserva.

foo = x (Supponendo foo è un ivar) non chiama alcun metodo. Nessuno. Assegna il valore del puntatore in x al puntatore in foo. Se foo Indicato qualcosa che è stato trattenuto, è trapelato. Se il nuovo valore che stai assegnando non è mantenuto, ti crollerai più tardi.

La soluzione a questo è utilizzare sempre gli accessori quando è possibile.

O.

L'uso della sintassi DOT è più pulito (ad alcuni) e si compila all'equivalente. cioè self.iVar equivale a [self iVar] e self.iVar = aValue equivale a [self setIVar:aValue];

self.aString è uno zucchero sintattico a [self aString]. Sintetizzare una proprietà basta creare il -aString e -setAString: Metodo (a seconda della proprietà che l'hai scelto pur non essere l'influenza banale).

Ora la domanda è se usare il . notazione. Ti suggerisco di non usarlo. Come mai? Innanzitutto sappi che l'obiettivo-C mira a essere solo un'aggiunta a C. Ciò significa che ogni codice C valido è anche un codice Objective-C valido.

Ora guarda cosa hanno fatto con la notazione punto. L'ultima affermazione non è più valida. Non distinguerai tra un accesso a un campo di una struttura C e l'invio del metodo Objective-C.

Quindi per favore non usare la notazione punto. Preferisci usare il [Self ..].

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top