iOS5 ARC可以安全地从背景选择器安排NSTimers吗?

时间:2011-11-09 05:09:10

标签: objective-c ios ios5 nstimer automatic-ref-counting

我正在尝试调试我的应用程序。

我一直在我的非弧代码中使用一些NSTimer实例(来自主线程):

[NSTimer scheduledTimerWithTimeInterval:5 target:musicPlayer selector:@selector(playPause:) userInfo:nil repeats:NO];

如果我将此代码分配给按钮并单击按钮,则此工作正常。计时器开火。

我也试过了:

 if( self.deliveryTimer == nil)
  {                 
self.deliveryTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(playPause:) userInfo:nil repeats:NO];
    }

    -(void)playPause:(NSTimer*)timer
    {
           [deliveryTimer invalidate];
            deliveryTimer = nil;
//more code here

    }

我希望定时器执行,按下面的播放/暂停方法,然后转到nil,这样我可以稍后重置定时器。我检查nil的原因是因为我有3个不同的代码路径可以设置定时器。每个都有一个NSLog语句,表明计时器已被安排。

我的代码运行了,我看到计时器正在安排,但是在正常的应用程序执行过程中它们似乎没有触发。我正在调查原因。短期计时器,使用相同的逻辑火。当我让应用程序运行一段时间时,我遇到了问题。

ARC可以回收NSTimers吗?

如果我从performSelectorInBackground设置计时器,这有关系吗?当我写这个问题时,我注意到我的一些计时器是通过一个被调用的代码路径创建的:

[self performSelectorInBackground:@selector(notifyDelegateOfDataPoint:) withObject:data];

背景选择器可能是我的计时器之前没有开火/回收的原因吗?

任何帮助都表示赞赏,这个bug已经困扰了我超过2周!

更新:更改代码以使用NSTimers的主线程后,计时器正确触发,从而导致音乐播放:

   [self performSelectorOnMainThread:@selector(deliverReminder:) withObject:nil waitUntilDone:NO];


-(void)deliverReminder:(id)sender{
     [ NSTimer scheduledTimerWithTimeInterval:10 target:reminderDeliverySystem selector:@selector(playAfterDelay:) userInfo:nil repeats:NO];
    [self postMessageWithTitle:nil message:@"Deliver Reminder Called" action:kNoContextAction];
}

-(void)playAfterDelay:(id)sender
{
    int reminderDelay = reminder.delayValue.intValue;

    [playTimers addObject:[NSTimer scheduledTimerWithTimeInterval:reminderDelay target:self selector:@selector(appMusicPlayerPlay:) userInfo:nil repeats:NO]];


}

这里有一大堆定时器,这是因为我不知道如何使用选择器将原语传递给目标。

1 个答案:

答案 0 :(得分:6)

NSTimer需要在后台线程中运行一个运行循环才能继续触发。主线程已经有一个活动的运行循环,这就是为什么你的定时器在执行它时工作正常。

如果要在后台线程中使用计时器,可以执行以下操作:

NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
self.deliveryTimer = [NSTimer scheduledTimerWithTimeInterval:10 target:self selector:@selector(playPause:) userInfo:nil repeats:NO];
[runLoop run];

你的短持续时间计时器可能会发生什么,但是较长的计时器没有,是因为它们在线程仍然处于活动状态时触发,但没有运行循环来保持它继续,在线程到达结束后失败它的执行。

我不相信这与ARC有关,虽然你可能需要注意一些东西,因为NSRunLoop持有一个附加到它的计时器。遵循NSTimers的标准程序应该避免ARC问题。