iPhone: invalidate NSTimer from app delegate crashes app
I am trying to run a method from my app delegate, that saves an object in other class as well as invalidates a timer. I have it set up so that when my app exits, it runs the method in my class and saves and stops the timer.
In app delegate:
- (void)applicationWillResignActive:(UIApplication *)application {
// Save the mission because they are leaving the app
if ([timeRun hasScore]) {
[timeRun resetWithSave];
}
}
The method it calls in the "timeRun" class:
- (void)resetWithSave {
// Save
self.counterInt = 150;
self.timer.text = [self timeInSeconds:counterInt];
[start setBackgroundImage:[UIImage imageNamed:@"play.png"] forState:UIControlStateNormal];
self.started = NO;
self.score.text = @"0";
[self saveMi开发者_开发技巧ssion];
if ([countTimer isValid]) {
[countTimer invalidate];
}
[table scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
}
But, I am getting crashes:
2010-09-11 19:35:21.503 Score Card[2747:307] -[__NSCFType isValid]: unrecognized selector sent to instance 0x19e190
2010-09-11 19:35:21.594 Score Card[2747:307] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType isValid]: unrecognized selector sent to instance 0x19e190'
*** Call stack at first throw:
(
0 CoreFoundation 0x30897ed3 __exceptionPreprocess + 114
1 libobjc.A.dylib 0x3002f811 objc_exception_throw + 24
2 CoreFoundation 0x30899683 -[NSObject(NSObject) doesNotRecognizeSelector:] + 102
3 CoreFoundation 0x308411d9 ___forwarding___ + 508
4 CoreFoundation 0x30840f90 _CF_forwarding_prep_0 + 48
5 Score Card 0x00006b3d -[TimeRun resetWithSave] + 272
6 Score Card 0x00002b39 -[Score_CardAppDelegate applicationWillResignActive:] + 80
7 UIKit 0x31ea6879 -[UIApplication _setActivated:] + 212
8 UIKit 0x31eda4ab -[UIApplication _handleApplicationSuspend:eventInfo:] + 238
9 UIKit 0x31eab301 -[UIApplication handleEvent:withNewEvent:] + 2200
10 UIKit 0x31eaa901 -[UIApplication sendEvent:] + 44
11 UIKit 0x31eaa337 _UIApplicationHandleEvent + 5110
12 GraphicsServices 0x31e4504b PurpleEventCallback + 666
13 CoreFoundation 0x3082cce3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 26
14 CoreFoundation 0x3082cca7 __CFRunLoopDoSource1 + 166
15 CoreFoundation 0x3081f56d __CFRunLoopRun + 520
16 CoreFoundation 0x3081f277 CFRunLoopRunSpecific + 230
17 CoreFoundation 0x3081f17f CFRunLoopRunInMode + 58
18 GraphicsServices 0x31e445f3 GSEventRunModal + 114
19 GraphicsServices 0x31e4469f GSEventRun + 62
20 UIKit 0x31e51123 -[UIApplication _run] + 402
21 UIKit 0x31e4f12f UIApplicationMain + 670
22 Score Card 0x000029ef main + 70
23 Score Card 0x000029a4 start + 40
)
terminate called after throwing an instance of 'NSException'
Program received signal: “SIGABRT”.
kill
quit
Why would this crash my app?
On a hunch, you're doing something like
countTimer = [NSTimer scheduledTimerWithTarget:...];
...
if ([countTimer isValid])
{
[countTimer invalidate];
}
...
if ([countTimer isValid])
{
[countTimer invalidate];
}
A "scheduled" timer is added to the run loop for you. It is then retained by the run loop. Invalidating it removes it from the run loop, thus it is released. If nothing else is retaining it, it is dealloced. When you try to use it again, it crashes.
Try something like [countTimer invalidate]; countTimer = nil;
Alternatively, you can retain the timer, but note that the timer retains its target so it's easy to end up with a retain cycle.
It looks like the timer was never initialized or it was released. Sometimes exceptions like that will be thrown with a random object when it is nil as well. Check your pointers and retain counts!
精彩评论