iPhone崩溃 - 消息发送到解除分配的实例

时间:2012-02-22 17:15:31

标签: iphone objective-c ios cocoa-touch ios-simulator

好的,这是我得到的错误:

    -[CFRunLoopTimer invalidate]: message sent to deallocated instance 0x109b05a0 (gdb)

以下是导致崩溃的代码:

    if (waitingOpponentTimer) {
      [waitingOpponentTimer invalidate]; //<-- Crash/error occurs here
      waitingOpponentTimer = nil;
    }

其他地方:

    NSTimer* waitingOpponentTimer;

还有:

    waitingOpponentTimer = [NSTimer scheduledTimerWithTimeInterval:10.0f target:self selector:@selector(waitingOpponentTimeOut)userInfo:nil repeats:NO];

waitOpponentTimer没有任何其他地方出现,只有我上面显示的那些。 waitingOpponentTimeOut操作只是设置了一些变量,对定时器或waitingOpponentTimer没有任何作用。

我已经尝试了以下所有IF语句,以防止达到invalidate语句:

    if (waitingOpponentTimer) {
    if ([waitingOpponentTimer retainCount] > 0) {
    if (waitingOpponentTimer.isValid) {
    if (waitingOpponentTimer != nil) {

但是在所有情况下,它仍然通过IF语句,然后使用invalidate语句导致崩溃。

所以我的问题是,为什么/如何在对象isValid并且不是nil并且它的retainCount大于零时导致错误的无效?

是否有其他方法可以检查此项以防止无效到达?

我是iphone编程的完整菜鸟,花了几个小时谷歌搜索试图解决这个问题,但无法弄清楚我做错了什么。任何帮助和建议赞赏!

编辑: 只是为了澄清,我使用它在运行之前手动停止计时器。我知道如果它用完了,它会使自身无效,这就是为什么我使用IF语句来检查它是否已经失效(但它不起作用)。所以我认为当这次崩溃发生时,计时器已经自动失效,但我如何检查它是否已经失效?

编辑: 好的,我在下面标出了正确答案。我不知道在没有保留定时器并且已经使自身无效的情况下,实际上有没有理由通过IF语句获取代码,但是如果要在IF语句中使用定时器,则总是使用RETAIN

以下是相关信息:Is there any reason to retain a scheduled NSTimer if you don't need to invalidate it?

3 个答案:

答案 0 :(得分:6)

你使用ARC吗?

waitingOpponentTimer = [[NSTimer scheduledTimerWithTimeInterval:10.0f target:self selector:@selector(waitingOpponentTimeOut)userInfo:nil repeats:NO] retain];

答案 1 :(得分:1)

尝试在启动计时器之前调用isValid

这种方式你无法意外地创建它的2个实例

想想这个

 waitingOpponentTimer = [NSTimer scheduledTimerWithTimeInterval:10.0f target:self selector:@selector(waitingOpponentTimeOut)userInfo:nil repeats:NO];

 waitingOpponentTimer = [NSTimer scheduledTimerWithTimeInterval:10.0f target:self selector:@selector(waitingOpponentTimeOut)userInfo:nil repeats:NO];

    [waitingOpponentTimer invalidate]

还有一个计时器漂浮在周围,如果你不期望它会引发问题就会触发。所以,我会在调用之前测试isValid

if ([waitingOpponentTimer isValid]
{
    [waitingOpponentTimer invalidate]

     waitingOpponentTimer = [[NSTimer scheduledTimerWithTimeInterval:10.0f target:self selector:@selector(waitingOpponentTimeOut)userInfo:nil repeats:NO] retain];
}else{

     waitingOpponentTimer = [[NSTimer scheduledTimerWithTimeInterval:10.0f target:self selector:@selector(waitingOpponentTimeOut)userInfo:nil repeats:NO] retain];
}

答案 2 :(得分:0)

最有可能的是,您不需要使计时器无效。由于计时器不重复,一旦分配的时间到达结束,它将自动失效。这也可能是应用程序崩溃的原因。如果计时器已到达其运行结束,它会向自身发送无效消息,因此当您稍后调用它时,它不知道该怎么做,因为它已经失效。所以我的建议是忽略失效,因为它会处理自己(只要它不重复)