我想使用NSTimer
运行BackGround thread
,因为我已经编写了以下代码,但我的NSTimer
方法无法调用!
请一位有人帮助我
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSOperationQueue* operationQueue = [[NSOperationQueue alloc] init];
[operationQueue addOperationWithBlock:^{
// Perform long-running tasks without blocking main thread
[NSTimer scheduledTimerWithTimeInterval:2
target:self
selector:@selector(targetMethod)
userInfo:nil
repeats:YES];
}];
}
-(void)targetMethod{
NSLog(@"Timer Called");
}
答案 0 :(得分:1)
首先,您应该通过调用scheduledTimerWithTimeInterval在主线程上创建计时器。将调用scheduledTimerWithTimerInterval调用到operationQueue是没有意义的。定时器从它们的线程的runloop中调用。尝试使用不同的operationQueue调度它们会让你遇到麻烦。
如果您希望在后台执行计时器的实际操作,请在计时器回调方法中使用dispatch_async(...)在后台运行代码。
除非您有正当理由不这样做,否则请在主线程上安排计时器。
您的回调方法应该有一个计时器参数。这样,您的回调方法可以操作计时器,例如通过使其无效。 scheduledTimer ...也返回计时器。通常,您将存储该计时器对象,以便在视图消失时使其无效。如果不这样做,每次调用viewDidLoad时都会得到一个新的NSTimer。也就是说,当您的应用程序运行时,您将有越来越多的计时器回调。
学习GCD(大中央调度)。它比操作队列简单得多。除非有充分的理由,否则不应使用操作队列。
当你问“我们如何停止后台线程”时 - 你没有。您将代码分派给它,代码运行,只要有代码被调度,它就会运行。如果没有代码调度后台,它将停止运行,直到您再次发送代码。这就是它应该如何工作。
如果你的意思是“如何停止计时器” - 那就是无效的。
PS。如果您想从后台线程(您不想要,请相信我)安排计时器,可以在此处找到正确的答案:iOS5 ARC is it safe to schedule NSTimers from background selectors?
答案 1 :(得分:0)
您可以为BackGround线程使用GCD调度队列:=
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void)
{
NSTimer *timer = [NSTimer timerWithTimeInterval:0.5
target:self
selector:@selector(timerFired)
userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
dispatch_async(dispatch_get_main_queue(), ^(void)
{
});
});
答案 2 :(得分:0)
NSTimer
实际上并未在线程上运行。将计时器安排到主线程(实际上是它的NSRunLoop
)仍然允许它在计时器触发之前处理事件并执行其他操作。
当计时器触发时,主线程NSRunLoop
将调用目标+选择器,然后继续等待下一个事件。
我建议你用以下代码替换你的代码:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[NSTimer scheduledTimerWithTimeInterval:2
target:self
selector:@selector(targetMethod)
userInfo:nil
repeats:YES];
}
-(void)targetMethod{
NSLog(@"Timer Called");
}
注意:如果targetMethod
需要执行昂贵的操作,建议将它们安排到后台线程。