16

Sono nuovo allo sviluppo di iOS in generale e non ho mai trattato il conteggio dei riferimenti manuale (mantenimento, rilascio, autorelease). In quanto tale, non ho una buona comprensione di ciò che la magia ARC sta eseguendo.Qual è il modo corretto per dichiarare una proprietà readonly per iOS utilizzando ARC

ho pensato ho capito fino a quando mi è stato chiesto che tipo di proprietà (weak, strong, assign, ecc) dovrebbe essere dato a una proprietà di sola lettura che punta ad un oggetto, come ad esempio:

@property (readonly,nonatomic) NSString* name; 

ho letto qui Questions about a readonly @property in ARC che lo smantellamento dello strong/weak non verrà effettivamente compilato a meno che non venga specificata una variabile di supporto quando si utilizza la proprietà @synthesize; Ho solo così è capitato di essere specificando un Ivar supporto come questo:

@synthesize name = _name; 

Ora capisco che il 'qualificatore vita' di default di una variabile è forte, da qui: http://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226-CH1-SW4

Quindi, per farla breve - Sto definendo indirettamente la mia proprietà come (readonly,nonatomic,strong) come ivar _name implicitamente dichiarato come __strong.

ho alcune domande:

  1. E` strong il qualificatore vita corretto da usare? Presumo che lo sia, altrimenti l'oggetto che supporta il mio NSString* non sarebbe di proprietà da nessuna parte e verrebbe quindi liberato automaticamente (proveniente da Java, questo ha senso in quanto tutti i riferimenti sono forti per impostazione predefinita).

  2. Esistono altri modificatori che hanno senso in questa situazione, ad esempio copy o assign?

  3. Vuol dichiarando la proprietà come (readonly,nonatomic,strong) e (readonly,nonatomic) fare alcuna differenza per il codice che consuma la proprietà? per esempio. dichiararlo senza la parola chiave strong causa il puntatore all'oggetto da memorizzare come __unsafe_unretained dove la proprietà strong si memorizzerebbe in un puntatore __strong?

Grazie!

EDIT

Quindi se ho capito ora vale quanto segue a sola lettura proprietà:

  • Per i non-NSObject * tipi (int, float, void *, ecc) utilizzare (readonly, assign).
  • Per i puntatori di oggetti, utilizzare (readonly, strong) o (readonly, copy) - questi funzionano allo stesso modo per le proprietà di sola lettura ma è possibile che si desideri la semantica della copia se si estende/sottoclasse e si dichiara la proprietà come readwrite.
  • Per i puntatori di oggetti, (readonly, weak) ha senso solo se si sta memorizzando un puntatore già debole in quella proprietà (quel puntatore deve essere forte altrove o l'oggetto sarà deallocato).
+0

nota che "forte" è implicito, quindi se si estende un readonly specificato '(readonly)' con '(strong)' funzionerà, ma '(copy)' non lo farà. Invece vedresti "ARC vieta di sintetizzare una proprietà ... con proprietà non specificate o attributo di memorizzazione". In questo caso è necessario essere espliciti nella definizione dell'intestazione '(readwrite, copy)'. Questo mi ha fatto inciampare per qualche minuto. –

risposta

12
  1. strong è corretto da usare se si desidera mantenere un forte (possedere) riferimento a qualunque cosa è che si punta a. Di solito, vuoi essere forte, ma per evitare riferimenti circolari (in particolare nelle relazioni genitore/figlio, dove se il genitore indica il bambino e il figlio indica il genitore, non saranno mai rilasciati) a volte hai bisogno di usare riferimenti deboli . Inoltre, se vuoi mantenere un puntatore su un oggetto che non possiedi ma vuoi che sia valido solo finché esiste, allora vuoi usare un puntatore debole perché quando viene deallocato dal proprietario, il puntatore verrà automaticamente impostato su nil e non punterà alla memoria che non dovrebbe essere.

  2. assign viene utilizzato con valori scalari ed è il setter predefinito. copy ha senso se si desidera eseguire automaticamente una copia dell'oggetto e impostare il puntatore sulla copia anziché puntare all'oggetto originale. Ha senso farlo solo se hai un bisogno specifico (di solito perché non vuoi che l'oggetto muti su di te).

  3. Il link che hai fornito che dimostra che __strong è il default (e quindi non hanno bisogno di specificarlo) si riferisce a variabili e non a proprietà dichiarate. L'impostazione predefinita per le proprietà dichiarate è assign, quindi sicuramente farà la differenza. Se si desidera assign tuttavia, non fa alcuna differenza se lo si specifica o meno (oltre a quello di essere chiari che è ciò che si voleva). EDIT: Tuttavia, come ha sottolineato Jacques, questo sta cambiando con LLVM 3.1 e il valore predefinito è cambiandoassign-strong. In questo caso, non fa assolutamente alcuna differenza se si specifica o no strong e si può lasciare fuori se si desidera. Personalmente penso che sia bello scriverlo (soprattutto perché c'è un conflitto tra le diverse versioni) in modo che tutti quelli che guardano il codice si trovino sulla stessa pagina. Altri potrebbero non essere d'accordo su questo punto. :)

Vorrei suggerire la lettura dei proprietà dichiarate sezione del L'Objective-C Programming Language qui: <document removed by Apple with no direct replacement>.

+0

Hanno effettivamente cambiato il valore predefinito per le proprietà, a partire dalla prossima versione (3.1) di Clang: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#ownership.spelling.property –

+0

Interessante ... Ora è è diverso tra ARC e codice non ARC. Grazie @JacquesCousteau! – lnafziger

+1

Ho già letto il link che hai dato molte volte, sfortunatamente trovo molto leggero informazioni utili, motivo per cui ti sto chiedendo qui. Per quanto riguarda la risposta, non ritengo che affronti la mia domanda che riguarda specificamente le proprietà di sola lettura. –

7

Un ulteriore punto: le proprietà possono essere ridichiarate da readonly a readwrite. Ad esempio, una sottoclasse può rendere una proprietà di sola lettura dalla superclasse lettura-scrittura, simile a quante classi di Cocoa hanno sottoclassi che aggiungono mutabilità. Allo stesso modo, una proprietà può essere di sola lettura pubblica, ma la classe può ridichiarla in lettura-scrittura per uso interno in un'estensione di classe. Quindi, quando la classe imposta la propria proprietà, può trarre vantaggio da un setter sintetizzato che esegue correttamente la gestione della memoria ed emette le notifiche di modifica di valore-chiave appropriate.

Allo stato attuale, tutti gli altri attributi della proprietà devono essere coerenti. È concepibile che il compilatore possa allentare questo requisito. (Alcuni lo considerano un bug). In ogni caso, questo è uno dei motivi per dichiarare una proprietà readonly con un attributo di proprietà come strong, copy o debole - in modo che corrisponda alla redecazione readwrite altrove.

Riguardo alla domanda 3, stai chiedendo se il qualificatore di proprietà influisce sul codice che chiama il getter?No, non è così.

+1

Quindi il modificatore strong/weak non fare qualche differenza in una proprietà readonly diversa dal cambiare il qualificatore lifetime dell'ivar sintetizzato, è corretto? –

+1

Sì, è corretto. –

+0

Grazie mille per il tuo aiuto! –

0

Queste 2 linee di lavoro codice per me:

file h:

@property (nonatomic, readonly, copy) NSString *username; 

di file .m:

@property (nonatomic, readwrite, copy) NSString *username; 
Problemi correlati