Разница между двумя способами итерации в цели C? - PullRequest
2 голосов
/ 27 февраля 2012

У меня есть проблема с двумя способами итерации.

NSArray *array=[[NSArray alloc] initWithObjects:@"A",@"B",@"C",@"D",nil];

NSMutableArray *mutArray=[[NSMutableArray alloc] initWithArray:array];

когда я так делаю, тогда все работает правильно

for (int i=0;[mutArray count]!=0;) {
    [mutArray removeObjectAtIndex:i];
}
NSLog(@"%d,",[mutArray count]);

Но когда мне это нравится, он падает ... почему?

for(id obj in mutArray)
{
    [mutArray removeObject:obj]
}
NSLog(@"%d,",[mutArray count]);

Пожалуйста, дайте мне решение для второго случая.

Ответы [ 4 ]

2 голосов
/ 27 февраля 2012

Второй случай называется быстрым перечислением. Вы не можете редактировать массив во время его быстрого перечисления из-за деталей реализации быстрого перечисления.

Я часто решаю эту проблему, выполняя следующие действия:

for(id obj in [[mutArray copy] autorelease])
{
    [mutArray removeObject:obj]
}
NSLog(@"%d,",[mutArray count]);

Таким образом, вы выполняете итерацию по временной копии массива, но вы можете изменять оригинал по мере прохождения.

p.s. Вы не можете редактировать во время быстрого перечисления, потому что быстрое перечисление работает, запрашивая у объекта массив C содержимого в начале перечисления. Как только это будет получено, итерация будет быстрой, поскольку между перечислениями нет вызовов сообщений Objective-C. Однако если вы измените массив, массив C больше не будет корректным представлением содержимого, поэтому возникает исключение.

2 голосов
/ 27 февраля 2012

Вы не должны изменять коллекцию во время ее быстрого перечисления.

Быстрое перечисление работает, запрашивая группу элементов из коллекции.Это делается для производительности и правильности.Так как вы перечисляете часть элементов, программе не нужно все время возвращаться к контейнеру.Но если вы изменяете коллекцию за спиной перечислителя, все гарантии правильности и времени жизни объекта теряются.

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

См. Также:-removeAllObjects.

0 голосов
/ 27 февраля 2012

Отключение коллекции делает недействительным перечислитель.Перечислитель «обнаруживает» изменение и вызывает ошибку.В быстром перечислении вы можете пометить, что нужно удалить, или использовать индексирование на 1-м месте.

0 голосов
/ 27 февраля 2012

Мое предложение:

NSMutableArray *temps = [NSMutableArray array];
for(id obj in mutArray)
{
    // checking condition here
    [temps addObject:obj];
}
[mutArray removeObjectsInArray:temps];
...