Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Collection <__NSArrayM: 0x7fa1f2711910> was mutated while being enumerated

There are number of questions with similar title but none them of helped me.

but i can relate solution of this 'NSGenericException', reason: Collection <__NSArrayM: 0x7fabb400> was mutated while being enumerated question with my question. Because this termination is happening when I'm adding,removing string object with array.

Error :

Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x7fa1f2711910> was mutated while being enumerated.'

First throw call stack:

(

0   CoreFoundation                      0x00000001087b8c65 __exceptionPreprocess + 165
1   libobjc.A.dylib                     0x0000000108422bb7 objc_exception_throw + 45
2   CoreFoundation                      0x00000001087b85c4 __NSFastEnumerationMutationHandler + 132
3                                       0x0000000107e24cf5 -[ProfessionalRegSecond tableView:didDeselectRowAtIndexPath:] + 773
4   UIKit                               0x0000000109759d71 -[UITableView _deselectRowAtIndexPath:animated:notifyDelegate:] + 347
5   UIKit                               0x000000010974deea -[UITableView _userSelectRowAtPendingSelectionIndexPath:] + 187
6   UIKit                               0x000000010968062c _applyBlockToCFArrayCopiedToStack + 314
7   UIKit                               0x00000001096804a6 _afterCACommitHandler + 533
8   CoreFoundation                      0x00000001086ebca7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
9   CoreFoundation                      0x00000001086ebc00 __CFRunLoopDoObservers + 368
10  CoreFoundation                      0x00000001086e1a33 __CFRunLoopRun + 1123
11  CoreFoundation                      0x00000001086e1366 CFRunLoopRunSpecific + 470
12  GraphicsServices                    0x000000010d6c8a3e GSEventRunModal + 161
13  UIKit                               0x000000010965c900 UIApplicationMain + 1282
14                                      0x0000000107de14cf main + 111
15  libdyld.dylib                       0x000000010b585145 start + 1
)

libc++abi.dylib: terminating with uncaught exception of type NSException

What I'm trying to do :

I need array in such way that when i select cell i want to add that object to array & when I'm deselecting row i want to remove that row from array so as a result array will be only selected entries. How to do this ?

Here is my code

@implementation Professional

    {
         NSMutableArray *updatedLocalityArray; // alloc,init did in viewDidLoad
         NSString *toCheck;
    }

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

   {

        UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];

        NSLog(@"%@",tableViewCell.textLabel.text);

        toCheck = tableViewCell.textLabel.text;
        [updatedLocalityArray addObject:toCheck];
        NSLog(@"%@ *****", updatedLocalityArray);

   }

  - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
    {

        UITableViewCell *tableViewCell = [tableView cellForRowAtIndexPath:indexPath];
           NSLog(@"%@",tableViewCell.textLabel.text);

        for (NSString *test in updatedLocalityArray)
        {
            if ([test isEqualToString:tableViewCell.textLabel.text])
            {

                [updatedLocalityArray removeObject:test];
                NSLog(@"%@ *****", updatedLocalityArray);

            }

        }

    }
like image 420
Shrikant K Avatar asked Sep 30 '15 12:09

Shrikant K


2 Answers

You cannot delete items from a NSMutableArray while iterating it.

There are several solutions to this:

  • Iterate a copy of the array

or

  • Use an index-based for loop instead of the for each syntax.

Not copying the array saves you an allocation and a few CPU cycles:

for (int i = updatedLocalityArray.count-1 ; i >= 0 ; i--)
{
    NSString *test = updatedLocalityArray[i];
    if ([test isEqualToString:tableViewCell.textLabel.text])
    {
        [updatedLocalityArray removeObjectAtIndex:i];
        NSLog(@"%@ *****", updatedLocalityArray);
    }
}
like image 127
Sergey Kalinichenko Avatar answered Oct 17 '22 02:10

Sergey Kalinichenko


In you tableview deselect method, you wrote:

for (NSString *test in updatedLocalityArray)
{
    if ([test isEqualToString:tableViewCell.textLabel.text])
    {
        [updatedLocalityArray removeObject:test];
        NSLog(@"%@ *****", updatedLocalityArray);
    }
}

In that code you are enumerating through updatedLocalityArray and if you find a match you are removing that object from same array, this logic is causing the issue here. For fixing that you need to create local copy and do the changes in it and assign it back to the original array after the enumeration.

NSMutableArray *tempArray = [updatedLocalityArray mutableCopy];
for (NSString *test in updatedLocalityArray)
{
    if ([test isEqualToString:tableViewCell.textLabel.text])
    {
        [tempArray removeObject:test];
        NSLog(@"%@ *****", tempArray);
    }
}
updatedLocalityArray = tempArray;
like image 20
Midhun MP Avatar answered Oct 17 '22 01:10

Midhun MP