Відповіді:
Як завжди у посилальних типах, існує два поняття "копія". Я впевнений, що ви їх знаєте, але для повноти.
Ви хочете останнього. Якщо це один із власних об'єктів, вам потрібно просто прийняти протокол NSCopying та реалізувати - (id) copyWithZone: (NSZone *) зону. Ви вільні робити все, що завгодно; хоча ідея полягає в тому, що ви робите справжню копію себе і повертаєте її. Ви викликаєте copyWithZone на всіх своїх полях, щоб зробити глибоку копію. Простий приклад - це
@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
, чи я щось тут пропускаю?
copyWithZone:
відповідає цим критеріям, тому він повинен повернути об’єкт із нескінченною кількістю +1.
alloc
замість того, allocWithZone:
як зона була передана?
allocWithZone
.
Документація Apple говорить
Версія підкласу методу copyWithZone: повинна надіслати повідомлення супер першим, щоб включити його реалізацію, якщо тільки підклас не походить безпосередньо з NSObject.
додати до існуючої відповіді
@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:'
. Я думаю, що це потрібно лише тоді, коли ми успадковуємо якийсь інший спеціальний клас, який реалізуєтьсяcopyWithZone
Я не знаю різниці між цим кодом і моїм, але у мене проблеми з цим рішенням, тому я прочитав трохи більше і виявив, що ми повинні встановити об'єкт, перш ніж повернути його. Я маю на увазі щось на кшталт:
#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;
}
Я додав цю відповідь, тому що у мене дуже багато проблем з цим питанням і не маю поняття, чому це відбувається. Я не знаю різниці, але це працює для мене, і, можливо, може бути корисним і для інших:)
another.obj = [obj copyWithZone: zone];
Я думаю, що цей рядок викликає протікання пам'яті, тому що ви отримуєте доступ до obj
через властивість, яка (я припускаю) оголошена як retain
. Отже, кількість утримань збільшиться на майно та copyWithZone
.
Я вважаю, що це повинно бути:
another.obj = [[obj copyWithZone: zone] autorelease];
або:
SomeOtherObject *temp = [obj copyWithZone: zone];
another.obj = temp;
[temp release];
Існує також використання оператора -> для копіювання. Наприклад:
-(id)copyWithZone:(NSZone*)zone
{
MYClass* copy = [MYClass new];
copy->_property1 = self->_property1;
...
copy->_propertyN = self->_propertyN;
return copy;
}
Міркування тут в результаті скопійованого об'єкта повинно відображати стан вихідного об'єкта. "". Оператор може вводити побічні ефекти, оскільки цей викликає одержувачів, які в свою чергу можуть містити логіку.