Search code examples
objective-cios5nstimerautomatic-ref-countingiphone-4

iPhone 4 iOS5 How to properly cancel several NSTimers at once with ARC?


I have several timers scheduled to play music at pre-determined intervals. I'm trying to find out if I'm cancelling them correctly, as my code does not seem to work because of the exception below.

I'm trying to add all timers to an NSMutableArray and then simply invalidate each one of them to prevent them from firing like this:

  [playTimers addObject:[NSTimer scheduledTimerWithTimeInterval:reminderDelay target:self selector:@selector(appMusicPlayerPlay:) userInfo:nil repeats:NO]];

I expect the stop method to go through the array and invalidate the timers. Should I call removeObject on the timer or is it easier to just re-allocate the array with ARC?

[Updated: here's the corrected solution to cancelling all timers at once]

-(int)stop
{
    [musicPlayer pause];
    [self pause];
    @try {
        for(NSTimer* timer in playTimers)
        {
            [timer invalidate];
        }
    }
    @catch (NSException *exception) {
        NSLog(@"exception: %@",[exception description]);
    }
    @finally {
        [playTimers removeAllObjects]

    }

    state = kRemoteControlStateStopped;
    return  state;
}

Here's the exception that I was catching after trying to remove an object from NSMutableArray while iterating over the array:

*** Collection <__NSArrayM: 0x5429330> was mutated while being enumerated.

Solution

  • You should not change the array contents while using a loop to iterate over the elements. You could always just invalidate all timers and call removeAllObjects on the array after that.