Подтвердить что ты не робот

Objective-C NSMutableArray мутировал при перечислении?

Я как-то наткнулся на ошибку, где вы пытаетесь удалить объекты из NSMutableArray, в то время как другие объекты добавляются к нему в другом месте. Чтобы это было просто, я не знаю, как это исправить. Вот что я делаю:

У меня есть 4 таймера, которые вызывают 4 разных метода, которые добавляют объект к одному и тому же массиву. Теперь, когда я нажимаю определенную кнопку, мне нужно удалить все объекты в массиве (или, по крайней мере, некоторые). Поэтому я попытался сначала аннулировать все 4 таймера, а затем выполнить работу, которую я хочу с помощью массива, а затем запустить таймеры. Я думал, что это сработало бы, так как я больше не использую таймеры для перечисления через массив, но, похоже, это не работает.

Любые предложения здесь?

4b9b3361

Ответ 1

Это не имеет никакого отношения к вашим таймерам. Потому что (я полагаю) ваши таймеры работают в том же потоке, что и ваш способ модификации, который вам не нужно останавливать и запускать. iOS не использует модель прерываний для обратных вызовов таймера, они должны ждать своего хода, как и любое другое событие:)

Вы, вероятно, делаете что-то вроде

for (id object in myArray)
   if (someCondition)
       [myArray removeObject:object];

Вы не можете редактировать измененный массив во время его прохождения, поэтому вам нужно сделать временный массив для хранения объектов, которые вы хотите удалить.

// Find the things to remove
NSMutableArray *toDelete = [NSMutableArray array];
for (id object in myArray)
   if (someCondition)
       [toDelete addObject:object];

// Remove them
[myArray removeObjectsInArray:toDelete];

Ответ 2

Вы можете сделать это следующим образом:

for (id object in [myArray copy])
   if (someCondition)
       [myArray removeObject:object];

Как и @deanWombourne, "вы не можете редактировать изменчивый массив, пока вы его проходите", поэтому я делаю здесь, чтобы создать автореализованную копию исходного массива для перечисления объектов, поэтому вы может безопасно удалить все, что вы хотите.

Более чистый и менее кодовый код (я думаю!).

Обновить. Удалено автозапуск, так как это был старый ответ, pre ARC.

Ответ 4

Хотя все верно... Я бы поделился своим опытом с

мутировался при перечислении

То, что я делал, было простым, но полным ошибкой:

for (id obj  in d.dataDashBoardGraph) {
    [tmpData addObject:[obj valueForKey:[[dataToShow[i] componentsSeparatedByString:@"_"] objectAtIndex:1]]];

    ...
}

Даже это вызвало mutated being enumerated error. Чтобы избавиться от него:

for (id obj  in d.dataDashBoardGraph) {
   NSString *data = [dataToShow[i] copy];
   [tmpData addObject:[obj valueForKey:[[data componentsSeparatedByString:@"_"] objectAtIndex:1]]];

    ... 
}

Тогда он работал отлично.

Ответ 5

Вы можете попробовать:

for (id object in [myArray reverseObjectEnumerator])
if (someCondition)
   [myArray removeObject:object];

Если вы удаляете объект по индексу x = > Индекс объектов с индексом x + 1, x + 2.... будет изменен. Поэтому, когда вы используете reverseObjectEnumerator, индекс объектов в массиве после удаления некоторых объектов будет по-прежнему исправляться.

Надеюсь на эту помощь. (принятый ответ - четкое решение.)

Ответ 6

NSMutableArray не может быть изменен во время перечисления, вы можете создать небольшую задержку перед вызовом вашего действия:

 for(id key in resultsDictionary) {
                if ([key isEqual:whichButtonString]) {
                   // [resultsDictionary removeObjectForKey:whichButtonString];
                    [self performSelector:@selector(removeKeyFromDictionary:) withObject:whichButtonString afterDelay:1.0];
                }
            }

Тогда

-(void) removeKeyFromDictionary : (NSString *) incomingString {
[resultsDictionary removeObjectForKey:incomingString];

}