У меня есть класс, представляющий структуру.
Этот класс с именем Object
имеет следующие свойства
@property (nonatomic, strong) NSArray *children;
@property (nonatomic, assign) NSInteger type;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, weak) id parent;
children
— это массив других Object
. parent
— это слабая ссылка на родительский объект.
Я пытаюсь скопировать и вставить ветку этой структуры. Если выбран корневой объект, parent
, очевидно, равно нулю. Если объект не является корнем, у него есть родитель.
Для этого объекты вида Object
должны соответствовать протоколам NSCopying
и NSCoding
.
Это моя реализация этих протоколов в этом классе.
-(id) copyWithZone: (NSZone *) zone
{
Object *obj = [[Object allocWithZone:zone] init];
if (obj) {
[obj setChildren:_children];
[obj setType:_type];
[obj setName:_name];
[obj setParent:_parent];
}
return obj;
}
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:@(self.type) forKey:@"type"];
[coder encodeObject:self.name forKey:@"name"];
NSData *childrenData = [NSKeyedArchiver archivedDataWithRootObject:self.children];
[coder encodeObject:childrenData forKey:@"children"];
[coder encodeConditionalObject:self.parent forKey:@"parent"]; //*
}
- (id)initWithCoder:(NSCoder *)coder {
self = [super init];
if (self) {
_type = [[coder decodeObjectForKey:@"type"] integerValue];
_name = [coder decodeObjectForKey:@"name"];
_parent = [coder decodeObjectForKey:@"parent"]; //*
NSData *childrenData = [coder decodeObjectForKey:@"children"];
_children = [NSKeyedUnarchiver unarchiveObjectWithData:childrenData];
_parent = nil;
}
return self;
}
Возможно, вы заметили, что у меня нет ссылки на получение или сохранение self.parent
в initWithCoder:
и encodeWithCoder:
, и поэтому каждый подобъект объекта имеет parent = nil.
Я просто не знаю, как это хранить. Просто из-за этого. Предположим, у меня есть эта структура Object
.
ObjectA > ObjectB > ObjectC
Когда encoderWithCoder:
начинает свою магическую кодировку ObjectA
, она также будет кодировать ObjectB
и ObjectC
, но когда она начинает кодировать ObjectB
, она находит родительскую ссылку, указывающую на ObjectA
, и запускает ее снова, создавая циклическую ссылку, которая зависает в приложении. Я пробовал это.
Как мне закодировать/восстановить эту родительскую ссылку?
Что мне нужно, так это сохранить объект и к моменту восстановления восстановить новую копию, идентичную той, что была сохранена. Я не хочу восстанавливать тот же объект, который был сохранен, а скорее копию.
ПРИМЕЧАНИЕ. Я добавил строки, отмеченные //*
, как предложил Кен, но _parent
равно нулю на initWithCoder:
для объектов, которые должны иметь parent