2012-04-24 3 views
1

Мне нужно время от времени удалять объект массива, когда я делаю это, я получаю эту ошибку.CALayerArray был мутирован при перечислении

Коллекция < CALayerArray: 0xc4f3b20> мутировали в то же время перечисленные

на этом методе, который является accesor из массива появляется ошибка:

- (NSArray *)occupantsArray 
{ 
    if (dispatch_get_current_queue() == moduleQueue) 
    { 
     return occupantsArray; 
    } 
    else 
    { 
     __block NSArray *result; 

     dispatch_sync(moduleQueue, ^{ //ON THIS LINE 
      result = [occupantsArray copy]; 
     }); 

     return [result autorelease]; 
    } 
} 

Как вы можете видеть Im заботясь о том, чтобы не возвращать исходный массив, а копировать, но он по-прежнему падает.

Также метод, в котором Im удаляет элементы массива.

- (void)eraseJIDFromArray:(NSString*)jid{ 

    dispatch_block_t block = ^{ 
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
     int i = 0; 
     for(NSString *jidAct in occupantsArray){ 
      if([jidAct isEqualToString:jid]){ 
       [occupantsArray removeObjectAtIndex:i]; 
      } 
      i++; 
     } 
     [pool drain]; 
    }; 

    if (dispatch_get_current_queue() == moduleQueue) 
     block(); 
    else 
     dispatch_async(moduleQueue, block); 



} 

Массив может иметь ДО 200 элементов, так что это может занять некоторое время, чтобы пройти через все из них, но я настройки очередей, не знаю, что еще я могу сделать.

Любые идеи?

Спасибо.

+0

Не проверять, является ли очередь текущей. Созданная очередь может иметь целевую очередь, что означает, что одна очередь может работать в другой очереди, что воронки работают в другой очереди и т. Д. 'Dispatch_get_current_queue' не может возвращать каждую вовлеченную очередь. Просто всегда отправляйте свою работу и доверяйте GCD встроенной работе, если это возможно и безопасно. – Jesper

+0

Должен ли я создать новую очередь? – subharb

+0

Нет, всегда вызывайте dispatch_async или dispatch_sync, чтобы сообщить GCD что-то сделать в очереди. Если вы в настоящий момент находитесь в очереди или нет, это не имеет значения, поскольку вам следует избегать dispatch_sync, если вы не можете * гарантировать *, что вы не находитесь в потоке очереди. – Jesper

ответ

4

Этот код:

for(NSString *jidAct in occupantsArray){ 
    if([jidAct isEqualToString:jid]){ 
     [occupantsArray removeObjectAtIndex:i]; 
    } 
    i++; 
} 

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

NSMutableIndexSet *indexes = [NSMutableIndexSet set]; // assuming NSInteger i; 
for(NSString *jidAct in occupantsArray){ 
    if([jidAct isEqualToString:jid]){ 
     [indexes addIndex:i]; 
    } 
    i++; 
} 
[occupantsArray removeObjectsAtIndexes:indexes]; 
+0

Спасибо, это отлично работает и не нуждается в потоках. – subharb

Смежные вопросы