开发者

How to properly invalidate an NSTimer

I've got an iPhone app with an NSTimer called pressTimer that goes off every time someone touches this button. The problem is they touch the button a lot, and I want the timer to stop when they lift up their finger. So I declared pressTimer in my .h and synthes开发者_运维百科ized it in .m then assigned and started it on the TouchDown action I created. I use the code [pressTimer invalidate] on my TouchUpInside action that should cancel the timer, since it's a global variable. It seems to cancel the timer fine, but then when I go to actually trip the timer, the program freezes up completely, even though I get no code errors or warnings. I'm a noob, so please don't be too rough :0

Update: Console logs- Thanks guys!

continue
2010-07-01 16:39:30.981 Clickkr[1573:307] -[__NSCFData invalidate]: unrecognized selector sent to instance 0x154b40
2010-07-01 16:39:30.999 Clickkr[1573:307] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFData invalidate]: unrecognized selector sent to instance 0x154b40'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x309a5fd3 __exceptionPreprocess + 114
    1   libobjc.A.dylib                     0x318b58a5 objc_exception_throw + 24
    2   CoreFoundation                      0x309a9a77 -[NSObject(NSObject) doesNotRecognizeSelector:] + 102
    3   CoreFoundation                      0x309a8f15 ___forwarding___ + 508
    4   CoreFoundation                      0x3093b680 _CF_forwarding_prep_0 + 48
    5   Clickkr                             0x00002b23 -[MyViewController addOne:] + 42
    6   CoreFoundation                      0x309307ad -[NSObject(NSObject) performSelector:withObject:withObject:] + 24
    7   UIKit                               0x31e1f829 -[UIApplication sendAction:to:from:forEvent:] + 84
    8   UIKit                               0x31e1f7c9 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 32
    9   UIKit                               0x31e1f79b -[UIControl sendAction:to:forEvent:] + 38
    10  UIKit                               0x31e1f4ed -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 356
    11  UIKit                               0x31e1fb3b -[UIControl touchesEnded:withEvent:] + 342
    12  UIKit                               0x31e1e4ed -[UIWindow _sendTouchesForEvent:] + 368
    13  UIKit                               0x31e1de67 -[UIWindow sendEvent:] + 262
    14  UIKit                               0x31e19b5b -[UIApplication sendEvent:] + 298
    15  UIKit                               0x31e19507 _UIApplicationHandleEvent + 5022
    16  GraphicsServices                    0x30a8c147 PurpleEventCallback + 666
    17  CoreFoundation                      0x3097baab __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 26
    18  CoreFoundation                      0x3097d84f __CFRunLoopDoSource1 + 166
    19  CoreFoundation                      0x3097e62d __CFRunLoopRun + 520
    20  CoreFoundation                      0x309278eb CFRunLoopRunSpecific + 230
    21  CoreFoundation                      0x309277f3 CFRunLoopRunInMode + 58
    22  GraphicsServices                    0x30a8b6ef GSEventRunModal + 114
    23  GraphicsServices                    0x30a8b79b GSEventRun + 62
    24  UIKit                               0x31dc32a7 -[UIApplication _run] + 402
    25  UIKit                               0x31dc1e17 UIApplicationMain + 670
    26  Clickkr                             0x00002333 main + 70
    27  Clickkr                             0x000022e8 start + 40
)
terminate called after throwing an instance of 'NSException'
Program received signal:  “SIGABRT”.


This is the way I invalidate timers:

[timer invalidate];
timer = nil;

The problem you're probably having is that once your timer is invalidated, it is removed from the runtime loop and when someone wants to access it, your program crashes. After invalidating it, just make it so that it is nil. That way if someone wants to send a message or do anything to it, it'll send it to nil.


@interface
  NSTimer * yourTimer;

@property (nonatomic, retain) yourTimer;
@synthesize yourTimer;

@implement    
  self.yourTimer = [NSTimer scheduledTimerWithTimeInterval:5
                                                    target:self
                                                  selector:@selector(yourSelector)
                                                  userInfo:nil
                                                   repeats:NO];

  //Wherever you want to stop the timer,
  [yourTimer invalidate];
  self.yourTimer = nil;


The log tells something wrong with addOne ... how's it related to the timer?


Guys I figured it out after a little bit of messing with it. Anauel's method for stopping timers worked great, but for some reason my method name was clashing with the timer's selector, so I changed them both. I also added Anauel's code to the method I used as a selector. Thanks!


I would better add a check of the validity flag and timer object instance

-(void) clearKeepAliveTimer {
    if(keepAliveTimer && [keepAliveTimer isValid]) {
        [keepAliveTimer invalidate];
        keepAliveTimer = nil;
    } }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜