копировать объекты из одного NSMutableArray в другой NSMutableArray - PullRequest
0 голосов
/ 27 марта 2011

Я пытаюсь понять, как копировать объекты из одного NSMutableArray в другой. Рассмотрим следующие 2 сценария: 1 - копирование оригинала в клон, когда изменения в клоне будут влиять на оригинал. 2 - копирование оригинала в клон, если изменения при закрытии НЕ влияют на оригинал.

Сначала я пытаюсь сначала создать сценарий № 1 со следующим кодом. Из того, что я понимаю, при копировании массива, не использующего 'mutablecopy', массив клонов будет просто содержать указатель на те же строковые объекты в оригинале. Так что, если бы я изменил первый элемент клона на другой объект, первый элемент оригинала тоже изменился бы, верно? ... но это не результат, который я получаю. Почему?

На самом деле, когда я использую mutablecopy

[self.cloneArray addObject:[[self.originalArray objectAtIndex:i] mutableCopy]];

Я получаю тот же результат. Я в замешательстве.

ArrayClass.h

@interface ArrayClass : NSObject {
    NSMutableArray *_originalArray;
    NSMutableArray *_cloneArray;
}

@property (nonatomic, retain) NSMutableArray *originalArray;
@property (nonatomic, retain) NSMutableArray *cloneArray;

ArrayClass.m

@synthesize originalArray = _originalArray;
@synthesize cloneArray = _cloneArray;

_originalArray = [[NSMutableArray alloc] initWithObjects: @"one", @"two", @"three", @"four", @"five", nil];
_cloneArray = [[NSMutableArray alloc] initWithCapacity:[self.originalArray count]];

for (int i=0; i<5; i++) {
    [self.cloneArray addObject:[self.originalArray objectAtIndex:i]];
}

// make change to the first element of the clone array
[self.cloneArray replaceObjectAtIndex:0 withObject:@"blah"];

for (int n=0; n<5; n++) {
    NSLog(@"Original:%@ --- Clone:%@", [self.originalArray objectAtIndex:n], [self.cloneArray objectAtIndex:n]);
}

...

2011-03-27 03:23:16.637 StringTest[1751:207] Original:one --- Clone:blah
2011-03-27 03:23:16.638 StringTest[1751:207] Original:two --- Clone:two
2011-03-27 03:23:16.639 StringTest[1751:207] Original:three --- Clone:three
2011-03-27 03:23:16.642 StringTest[1751:207] Original:four --- Clone:four
2011-03-27 03:23:16.643 StringTest[1751:207] Original:five --- Clone:five

Ответы [ 2 ]

8 голосов
/ 27 марта 2011

Вы слишком об этом думаете.

В Objective-C у вас есть ссылки на объекты. NSString *foo; просто определяет переменную foo, которая ссылается на NSString. Если вы скажете NSString *bar = foo;, тогда bar будет иметь ссылку на любой объект, на который ссылался foo. Не больше, не меньше.

NSArray - это просто набор ссылок на объекты. Итак, если вы скажете:

NSArray *b = [NSArray arrayWithArray: a];

Вы создаете массив b, который содержит все те же ссылки на тот же набор объектов, что и a. Если вы измените объект, на который указывает a, это будет точно такой же объект в b, и это изменение будет отражено.

Когда вы копируете объект, вы создаете новый объект, который имеет такое же внутреннее состояние, что и оригинал. То есть когда вы говорите NSMutableString *foo = [barString mutableCopy];, тогда foo является ссылкой на новую строку; отличный от barString.

Итак ... при создании нового массива возникает вопрос: хотите ли вы, чтобы массив содержал то же самое содержимое, что и исходный массив, или вы хотите, чтобы он содержал новый набор объектов, которые Вы можете изменить?

5 голосов
/ 27 марта 2011

Вы неправильно понимаете, что происходит.Вызов replaceObjectAtIndex:withObject: не изменяет объекты в массиве, он изменяет сам массив.После этой строки:

[self.cloneArray replaceObjectAtIndex:0 withObject:@"blah"];

вы заменили объект в своем массиве клонов, но вы вообще не изменили исходный массив.Если вы на самом деле изменили объект NSString, который вы поместили в массивы, вы могли бы получить ожидаемое поведение.Вы не сможете сделать это с объектами, которые вы поместили в исходный массив в вашем примере, поскольку они являются неизменяемыми строковыми объектами.Если вы вставили туда изменяемые строки, использовали один и тот же цикл для «клонирования» вашего массива, а затем сделали что-то вроде:

[[self.cloneArray objectAtIndex:0] appendString:@"some junk to append"];

, вы фактически изменили бы строковый объект с индексом 0. Поскольку обаМассивы по-прежнему содержат тот же объект, вы получите поведение «изменить исходный массив путем изменения объектов в массиве клонов».

...