我正在尝试调试我的应用程序。
我一直在我的非弧代码中使用一些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]];
}
这里有一大堆定时器,这是因为我不知道如何使用选择器将原语传递给目标。
答案 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问题。