NSMutableArray Objective-C мутировал при перечислении? - PullRequest
37 голосов
/ 12 января 2012

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

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

Есть предложения?

Ответы [ 6 ]

108 голосов
/ 12 января 2012

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

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

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

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

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

// Remove them
[myArray removeObjectsInArray:toDelete];
24 голосов
/ 12 января 2012

Вы можете сделать это так:

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

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

Более понятный и меньший код котла (я думаю!).

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

5 голосов
/ 03 октября 2012

Вы можете использовать директиву @synchronized (), чтобы заблокировать массив во время его изменения:

if (someCondition) {
    @synchronized(yourArray) {
        [yourArray removeObject:someObject];
    }
}

Дополнительная информация на http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocThreading.html

0 голосов
/ 12 февраля 2016

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

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

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

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

0 голосов
/ 24 августа 2015

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];

}

0 голосов
/ 23 июня 2015

Хотя прежде всего это правда ... Я бы поделился своим опытом с

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

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

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]]];

    ... 
}

Тогда все заработало отлично.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...