2009-02-25 20 views
16

Sto osservando l'applicazione di esempio di Apple EditableDetailView e ho notato che in uno dei loro controllori stanno impostando un'istanza della proprietà NSString con (nonatomic, copy). Quando si userebbe la copia invece di conservare? È così che possono fare una copia unica senza influenzare i dati esistenti?NSString @property, usando la copia invece di conservare

+2

Il consiglio è di utilizzare la copia per le classi che fanno parte di un cluster di classi che hanno coppie mutabili/immutabili; come 'NSString' /' NSMutableString' 'NSArray' /' NSMutableArray' 'NSDictionary' /' NSMutableDictionary' 'NSSet' /' NSMutableSet', vedere la risposta di @ Abizern [QUI] (http://stackoverflow.com/questions/4995254/NSMutableString-as-mantenere-copy). – Kjuly

risposta

38

Sì, è in modo che possa eseguire una copia univoca senza influire sui dati esistenti. I setter sintetizzati sembrano essenzialmente come questo:

// For @synthesize(nonatomic, retain) foo: 
- (void) setFoo(NSFoo *theFoo) 
{ 
    [theFoo retain]; // retain new value 
    [foo release]; // release old value, if any 
    foo = theFoo;  // assign new value 
} 

// For @synthesize(nonatomic, copy) foo: 
- (void) setFoo(NSFoo *theFoo) 
{ 
    NSFoo* newFoo = [theFoo copy]; // make copy 
    [foo release]; // release old value, if any 
    foo = newFoo; // assign new value 
} 

Nota l'ordine delle operazioni qui è importante - il nuovo valore deve essere mantenuto/copiato prima che il vecchio valore viene rilasciato, in caso di auto-assegnazione. Se prima si rilasciava e poi si assegnava la proprietà a se stessa, si poteva deallocare il valore per errore. Si noti inoltre che se il vecchio valore è nil, inviarlo un messaggio release è ok, poiché l'invio di un messaggio a un oggetto nil è esplicitamente consentito e non fa nulla.

La scelta del mantenimento rispetto alla copia determina solo se la proprietà dell'oggetto condivide lo stesso valore con quello a cui si sta impostando. Si consideri il seguente codice:

// suppose the 'foo' property is declared 'retain' and the 'bar' property is 
// declared 'copy' 
NSFoo *foo = ...; 
NSBar *bar = ...; 
someObject.foo = foo; 
someObject.bar = bar; 
[foo changeInternalState]; // someObject.foo also changes, since it's the same object 
[bar changeInternalState]; // someObject.bar does NOT change, since it's a copy 
+0

potrebbe esserci un errore di battitura nell'ultima riga. dove //someObject.foo NON ... dovrebbe essere //someObject.bar NON –

+0

Per poter chiamare 'copia' su un oggetto Classe personalizzato, è necessario sovrascrivere il metodo' copyWithZone: '. – thesummersign

3

Ricordate che c'è un NS Mutevole String. Sarebbe davvero pessimo essere in grado di mutare il contenuto di una stringa posseduta da un altro oggetto (ad esempio cancellando metà dei suoi caratteri), specialmente se non ti rendi conto che stai influenzando un altro oggetto. Pertanto, è bello che l'altro oggetto esegua la propria copia.

Si può dire "bene, perché non copio semplicemente la stringa prima di assegnarla lì?". Forse l'oggetto vuole una stringa mutabile e la tua è immutabile. Se devi prima copiare la stringa, devi cercare il tipo di stringa che desidera nella sua documentazione o intestazione, quindi creare il giusto tipo di copia (ogni volta). In questo modo, dici semplicemente other.string = myString e fa qualunque tipo di copia desideri - non devi preoccuparti di questo.

0

(Per qualche ragione, questo post viene visualizzato sopra la domanda di follow-up che sto cercando di rispondere) Re:

volevi dire che devo copiare 'il foo' oggetto prima di rilasciare 'pippo' ?? ma qual è il problema se io reloese 'pippo' prima di copiare 'il pippo' ?? perché sono due diversi oggetto non riesco a capire perché rilasciare uno si interessa di altro !!!!

La maggior parte delle volte è corretto. Se sono, infatti, due oggetti separati, non avrà importanza. Il problema sta nella possibilità che tu stia assegnando lo stesso oggetto a se stesso. Se stavi per dire

[myObject setFoo: moof]; 
[myObject setFoo: moof]; 

Poi la seconda volta l'hai fatto, avresti rilasciato moof prima di copiarlo. Nel momento intermedio, è possibile che se il conto di conservazione di moof è azzerato, allora moof verrebbe eliminato e non avresti nulla da copiare nel passaggio seguente. Foo ora sarebbe zero.

È probabile che ciò accada? Probabilmente più di quanto potresti pensare. Ci sono certamente momenti in cui l'utente potrebbe cliccare due volte su un pulsante "aggiorna", ad esempio.

Spero che sia comprensibile e utile.

+1

Stack Overflow è un sito di domande e risposte, non un forum. Risposte, di cui sia questa che la "domanda" a cui intendevi rispondere, sono ordinate per voto per impostazione predefinita. Il tuo ha 0 e l'altra risposta (che ora è cancellata) è finita a -3, quindi la tua appare più alta (a quelli di noi che hanno abbastanza karma da vedere l'altro). Il modo giusto sarebbe stato di commentare l'altra risposta, ma ciò richiede 50 punti reputazione, che non hai. (Inoltre, la tua risposta è troppo profonda e ricca di formattazione per rientrare in un commento.) Non c'è un modo giusto nella tua situazione. –

Problemi correlati