xcode NSTimer 崩溃,当我调用 [Timer isValid] 或 [Timer invalidate]

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3692359/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 19:43:51  来源:igfitidea点击:

NSTimer crashes, when I call [Timer isValid] or [Timer invalidate]

iphoneobjective-cxcodecrashnstimer

提问by esanits

I have two NSTimers in my iPhone app. DecreaseTimer works fine, but TimerCountSeconds crashes when I call [timerCountSeconds isValid] or [timerCountSeconds invalidate]. They are used like this:

我的 iPhone 应用程序中有两个 NSTimer。DecreaseTimer 工作正常,但当我调用 [timerCountSeconds isValid] 或 [timerCountSeconds invalidate] 时 TimerCountSeconds 崩溃。它们是这样使用的:

-(id)initialize { //Gets called, when the app launches and when a UIButton is pressed
 if ([timerCountSeconds isValid]) {
  [timerCountSeconds invalidate];
 } 
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { //Gets called, when you begin touching the screen
 //....
 if ([decreaseTimer isValid]) {
   [decreaseTimer invalidate];
  }
 timerCountSeconds = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(runTimer) userInfo:nil repeats:YES];
 //....
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {//Gets called, when you stop touching the screen(not if you press the UIButton for -(id)initialize)
 //...
 decreaseTimer = [NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(decrease) userInfo:nil repeats:YES];
 //...
}
-(void)comept3 { //Gets calles when you rubbed the screen a bit
    if ([timerCountSeconds isValid]) {
    [timerCountSeconds invalidate];
    }
}

What did I do wrong? Can you please help me?

我做错了什么?你能帮我么?

回答by Shaggy Frog

You should set an NSTimerobject to nilafter you invalidateit, since the invalidatemethod call also does a release(as per the Apple docs). If you don't, calling a method on it like isValidcould cause your crash.

你应该在你之后设置一个NSTimer对象,因为方法调用也做了(根据 Apple 文档)。如果你不这样做,调用它的方法可能会导致你的崩溃。nilinvalidateinvalidatereleaseisValid

回答by jayesh kavathiya

 [objTimer retain];

Then it will not crash any time. Use this after initializing the timer so it will work fine....

然后它不会在任何时候崩溃。在初始化计时器后使用它,这样它就可以正常工作....

回答by Chuck

Most likely the timer stored in that variable has already been deallocated. You need to retain it if you want to keep it around for an arbitrarily long time.

很可能存储在该变量中的计时器已经被释放。如果您想将其保留任意长时间,则需要保留它。

回答by zzzz

You need to set the timer in main thread. NSTimer will not be fired in background thread.

您需要在主线程中设置计时器。NSTimer 不会在后台线程中被触发。

  • Objc:

    dispatch_async(dispatch_get_main_queue(), ^{
       _timer = [NSTimer scheduledTimerWithTimeInterval:delay target:self selector:@selector(YOUR_METHOD) userInfo:nil repeats:YES];
    });
    
  • Swift:

    dispatch_async(dispatch_get_main_queue()) {
       timer = NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: "YOUR_METHOD", userInfo: nil, repeats: true)
    }
    
  • 对象:

    dispatch_async(dispatch_get_main_queue(), ^{
       _timer = [NSTimer scheduledTimerWithTimeInterval:delay target:self selector:@selector(YOUR_METHOD) userInfo:nil repeats:YES];
    });
    
  • 迅速:

    dispatch_async(dispatch_get_main_queue()) {
       timer = NSTimer.scheduledTimerWithTimeInterval(delay, target: self, selector: "YOUR_METHOD", userInfo: nil, repeats: true)
    }
    

回答by olliej

You need to actually initialise the TimerCountSecondsand DecreaseTimermembers in initialise. Assuming you're control flow is:

您需要在初始化中实际初始化TimerCountSecondsDecreaseTimer成员。假设你的控制流是:

...
myObject = [[MyObject alloc] initialize];
...
[myObject touchesBegan:...]
...
[myObject touchesEnded:...]
...

Then when you call initializeTimerCountSecondshas not been initialised, so you're logically doing

然后当你调用initializeTimerCountSeconds还没有被初始化,所以你在逻辑上做

[<random pointer> isValid]

Which will crash. Similarly DecreaseTimer is invalid the first time you call touchesBegan.

哪个会崩溃。同样,第一次调用 touchesBegan 时,DecreaseTimer 无效。

In your initialise method you will need to actually initialise everything, before you attempt to use anything.

在您的初始化方法中,您需要在尝试使用任何东西之前实际初始化所有内容。

You also appear to be leaking timers (touchesBegininvalidates the timer but does not release it)

您似乎也在泄漏计时器(touchesBegin使计时器无效但不释放它)