Respostas:
Como sempre com os tipos de referência, existem duas noções de "cópia". Tenho certeza que você os conhece, mas para a integridade.
Você quer o último. Se este for um de seus próprios objetos, você precisa simplesmente adotar o protocolo NSCopying e implementar - (id) copyWithZone: (NSZone *) zone. Você é livre para fazer o que quiser; embora a ideia seja fazer uma cópia real de si mesmo e devolvê-la. Você chama copyWithZone em todos os seus campos para fazer uma cópia em profundidade. Um exemplo simples é
@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
, ou estou perdendo alguma coisa aqui?
copyWithZone:
atende a esse critério, portanto, deve retornar um objeto com uma contagem de retenção de +1.
alloc
vez de, allocWithZone:
já que a zona foi aprovada?
allocWithZone
.
A documentação da Apple diz
Uma versão de subclasse do método copyWithZone: deve enviar a mensagem para super primeiro, para incorporar sua implementação, a menos que a subclasse desça diretamente de NSObject.
para adicionar à resposta existente
@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:'
. Acho que isso só é necessário quando estamos herdando de alguma outra classe personalizada que implementacopyWithZone
Não sei a diferença entre esse código e o meu, mas tenho problemas com essa solução, então li um pouco mais e descobri que temos que definir o objeto antes de devolvê-lo. Quero dizer algo como:
#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;
}
Eu adicionei essa resposta porque tenho muitos problemas com esse problema e não tenho ideia do por que isso está acontecendo. Não sei a diferença, mas está funcionando para mim e talvez possa ser útil para os outros também:)
another.obj = [obj copyWithZone: zone];
Eu acho que essa linha causa vazamento de memória, porque você acessa obj
através da propriedade que é (presumo) declarada como retain
. Portanto, a contagem retida será aumentada por propriedade e copyWithZone
.
Eu acredito que deveria ser:
another.obj = [[obj copyWithZone: zone] autorelease];
ou:
SomeOtherObject *temp = [obj copyWithZone: zone];
another.obj = temp;
[temp release];
Também existe o uso do operador -> para copiar. Por exemplo:
-(id)copyWithZone:(NSZone*)zone
{
MYClass* copy = [MYClass new];
copy->_property1 = self->_property1;
...
copy->_propertyN = self->_propertyN;
return copy;
}
O raciocínio aqui é que o objeto copiado resultante deve refletir o estado do objeto original. O "." operador pode introduzir efeitos colaterais, pois este chama getters que, por sua vez, podem conter lógica.