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

发布于 2024-09-19 04:07:23 字数 1159 浏览 5 评论 0原文

我的 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];
    }
}

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

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:

-(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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

疧_╮線 2024-09-26 04:07:23

invalidate 后,您应该将 NSTimer 对象设置为 nil,因为 invalidate 方法调用还会执行 < code>release (根据 Apple 文档)。如果不这样做,调用其上的方法(例如 isValid)可能会导致崩溃。

You should set an NSTimer object to nil after you invalidate it, since the invalidate method call also does a release (as per the Apple docs). If you don't, calling a method on it like isValid could cause your crash.

总以为 2024-09-26 04:07:23

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

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.

川水往事 2024-09-26 04:07:23
 [objTimer retain];

那么任何时候都不会崩溃。初始化定时器后使用它,这样它就能正常工作......

 [objTimer retain];

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

江湖彼岸 2024-09-26 04:07:23

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

  • 对象:

    dispatch_async(dispatch_get_main_queue(), ^{
       _timer = [NSTimer ScheduledTimerWithTimeInterval:延迟目标:self 选择器:@selector(YOUR_METHOD) userInfo:nil 重复:YES];
    });
    
  • Swift:

    dispatch_async(dispatch_get_main_queue()) {
       计时器= NSTimer.scheduledTimerWithTimeInterval(延迟,目标:self,选择器:“YOUR_METHOD”,userInfo:nil,重复:true)
    }
    

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

  • 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)
    }
    
情感失落者 2024-09-26 04:07:23

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

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

那么当你调用initialize时,TimerCountSeconds还没有被初始化,所以你逻辑上正在做的

[<random pointer> isValid]

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

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

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

You need to actually initialise the TimerCountSeconds and DecreaseTimer members in initialise. Assuming you're control flow is:

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

Then when you call initialize TimerCountSeconds has not been initialised, so you're logically doing

[<random pointer> isValid]

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

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

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

御守 2024-09-26 04:07:23
-(void)StopScanTimer
{
    if(scanTimer != nil)
    {
        [scanTimer invalidate];
        scanTimer = nil;
    }
}

-(void)StartScanTimer
{
    [self StopScanTimer];

    float duration = 10.0f;
    scanTimer = [NSTimer timerWithTimeInterval:duration target:self     selector:@selector(OnScanTimerElapsed) userInfo:nil repeats:NO];
    [[NSRunLoop mainRunLoop] addTimer:scanTimer forMode:NSRunLoopCommonModes];
    [scanTimer retain];
}

-(void) OnScanTimerElapsed
{
    // Do something
}

如果去掉“[scanTimerretain];”,调用invalidate时就会崩溃。
如果您想重新使用计时器,请务必保留它。

-(void)StopScanTimer
{
    if(scanTimer != nil)
    {
        [scanTimer invalidate];
        scanTimer = nil;
    }
}

-(void)StartScanTimer
{
    [self StopScanTimer];

    float duration = 10.0f;
    scanTimer = [NSTimer timerWithTimeInterval:duration target:self     selector:@selector(OnScanTimerElapsed) userInfo:nil repeats:NO];
    [[NSRunLoop mainRunLoop] addTimer:scanTimer forMode:NSRunLoopCommonModes];
    [scanTimer retain];
}

-(void) OnScanTimerElapsed
{
    // Do something
}

If you remove "[scanTimer retain];", it will crash when you call invalidate.
Always retain the timer if you want to use it back.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文