Risposte:
Come sempre con i tipi di riferimento, ci sono due nozioni di "copia". Sono sicuro che li conosci, ma per completezza.
Tu vuoi il secondo. Se questo è uno dei tuoi oggetti, devi semplicemente adottare il protocollo NSCopying e implementare - (id) copyWithZone: (NSZone *) zone. Sei libero di fare quello che vuoi; anche se l'idea è che tu faccia una copia reale di te stesso e la restituisci. Chiami copyWithZone su tutti i tuoi campi, per fare una copia completa. Un semplice esempio è
@interface YourClass : NSObject <NSCopying>
{
SomeOtherObject *obj;
}
// In the implementation
-(id)copyWithZone:(NSZone *)zone
{
// We'll ignore the zone for now
YourClass *another = [[YourClass alloc] init];
another.obj = [obj copyWithZone: zone];
return another;
}
autorelease
, o mi sto perdendo qualcosa qui?
copyWithZone:
soddisfa questo criterio, quindi deve restituire un oggetto con un conteggio di conservazione pari a +1.
alloc
invece che da allocWithZone:
quando la zona è stata passata?
allocWithZone
.
La documentazione di Apple dice
Una versione sottoclasse del metodo copyWithZone: dovrebbe inviare prima il messaggio a super, per incorporarne l'implementazione, a meno che la sottoclasse non discenda direttamente da NSObject.
da aggiungere alla risposta esistente
@interface YourClass : NSObject <NSCopying>
{
SomeOtherObject *obj;
}
// In the implementation
-(id)copyWithZone:(NSZone *)zone
{
YourClass *another = [super copyWithZone:zone];
another.obj = [obj copyWithZone: zone];
return another;
}
No visible @interface for 'NSObject' declares the selector 'copyWithZone:'
. Immagino che questo sia richiesto solo quando ereditiamo da un'altra classe personalizzata che implementacopyWithZone
Non conosco la differenza tra quel codice e il mio, ma ho problemi con quella soluzione, quindi ho letto un po 'di più e ho scoperto che dobbiamo impostare l'oggetto prima di restituirlo. Intendo qualcosa come:
#import <Foundation/Foundation.h>
@interface YourObject : NSObject <NSCopying>
@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSString *line;
@property (strong, nonatomic) NSMutableString *tags;
@property (strong, nonatomic) NSString *htmlSource;
@property (strong, nonatomic) NSMutableString *obj;
-(id) copyWithZone: (NSZone *) zone;
@end
@implementation YourObject
-(id) copyWithZone: (NSZone *) zone
{
YourObject *copy = [[YourObject allocWithZone: zone] init];
[copy setNombre: self.name];
[copy setLinea: self.line];
[copy setTags: self.tags];
[copy setHtmlSource: self.htmlSource];
return copy;
}
Ho aggiunto questa risposta perché ho molti problemi con questo problema e non ho idea del motivo per cui sta accadendo. Non conosco la differenza, ma per me funziona e forse può essere utile anche per gli altri :)
another.obj = [obj copyWithZone: zone];
Penso che questa riga provochi perdite di memoria, perché si accede a una obj
proprietà che è (presumo) dichiarata come retain
. Quindi, il conteggio della conservazione sarà aumentato dalla proprietà e copyWithZone
.
Credo che dovrebbe essere:
another.obj = [[obj copyWithZone: zone] autorelease];
o:
SomeOtherObject *temp = [obj copyWithZone: zone];
another.obj = temp;
[temp release];
C'è anche l'uso dell'operatore -> per la copia. Per esempio:
-(id)copyWithZone:(NSZone*)zone
{
MYClass* copy = [MYClass new];
copy->_property1 = self->_property1;
...
copy->_propertyN = self->_propertyN;
return copy;
}
Il ragionamento qui è che l'oggetto copiato risultante dovrebbe riflettere lo stato dell'oggetto originale. Il "." operatore potrebbe introdurre effetti collaterali in quanto questo chiama getter che a loro volta possono contenere logica.