0

My program has a NSMutable Array named as "matchedCards", and I have added few object in it of type Card, now I need to remove the objects from the array, and I use the following code for it:

for (Card * removeCards in matchedCards)
  {
    [self.matchedCards removeObject:removeCards];
  }

The first card-object gets removed , and after that the program gets crashed , Can anyone explain the reason behind it, if it successfully removes the first object, why it starts throwing error from 2nd object onwards

Abhi
  • 61
  • 1
  • 8
  • Your matchedCards array is dynamically getting its objects removed...and you are looping through the matchedCards array which will have its item count changed each time after you have removed a Object from it. – Srinivasan N Jun 19 '15 at 13:01

5 Answers5

2

You can't remove elements from an array while fast-enumerating it.
If you simply want to remove all objects do

[self.matchedCards removeAllObjects];

If you want to remove only certain elements however, remember their indices in an IndexSet and remove those

NSMutableIndexSet* indexesToRemove = [NSMutableIndexSet new];
for (NSUInteger index = 0; index < [self.matchedCards count]; ++index)  {
    if (whatever) {
        [indexesToRemove addObject:index];
    }
}


[self.matchedCards removeObjectsAtIndexes:indexesToRemove];
Pieter
  • 17,435
  • 8
  • 50
  • 89
  • i have to disagree with `You can't update an array while traversing it.`, my answer prove this statement wrong.. – 0yeoj Jun 19 '15 at 13:44
  • @0yeoj I thought it was kind of implied what I meant but you're right and I should've been more clear, clarified my answer – Pieter Jun 19 '15 at 13:51
  • It's okay, i just wanna clear things out and avoid confusion.. Cheers, brother. :) – 0yeoj Jun 19 '15 at 14:02
1

You can't remove an object from an array while iterating on it. Do this instead:

for (Card * removeCards in [matchedCards copy])
{
    [self.matchedCards removeObject:removeCards];
}
rounak
  • 9,217
  • 3
  • 42
  • 59
0

Read the crash log. It will say something along the lines of...

"Collection was stated while being enumerated"

Or something like that.

You can't mutate an array while iterating over it using a for:in loop.

You can do this though...

[matchedCards enumerateObjectsUsingBlock:^(Card *removedCards, NSInteger idx, BOOL *stop) {
    [self.matchedCards removeObject:card];
}];

Also, with your current code you are actually removing all of the objects from the matchedCards array. It will result in an empty array. Are you sure that's what you want?

Fogmeister
  • 76,236
  • 42
  • 207
  • 306
0
// if remove all objects
[matchedCards removeAllObjects];

// if you want to remove using index
for (int i =[matchedCards count]-1; i>=0; i++) {
   if (condition) {
       [matchedCards removeObjectAtIndex:i];
   }
}
MathieuF
  • 3,130
  • 5
  • 31
  • 34
Pravin Tate
  • 1,145
  • 8
  • 18
0

The reason is because you are removing the current object and ruin the for-statement

Here's a solution:

for (int i = 0; i < self.matchedCards.count; i++)
{
    if ([self.matchedCards[i] isKindOfClass:[YourClass class]])
    {
        [self.matchedCards removeObject:self.matchedCards[i]];

        i--; // invalidate the removed index
    }
}
NSLog(@"%@", self.matchedCards);

Take note that i-- is important, else you will not get through to the last element of the array..

Hope this helps you.. Cheers..

0yeoj
  • 4,500
  • 3
  • 23
  • 41