我想在GCD块中创建一个计时器(每2秒触发一次并调用一个方法)将其用作后台任务。但是,我认为计时器永远不会发火。这是我的代码:
- (void)startMessaging
{
BOOL queue = YES;
dispatch_queue_t _queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0,0, _queue);
dispatch_source_set_timer(timerSource, dispatch_walltime(NULL, 0), 2ull * NSEC_PER_SEC,1ull * NSEC_PER_SEC );
dispatch_source_set_event_handler(timerSource, ^{
if (queue) {
[self observeNewMsgs];
}
});
dispatch_resume(timerSource);
}
- (void)observeNewMsgs
{
NSLog(@"JUST TO TEST");
// Staff code...
}
那么这有什么问题?我该如何解决这个问题?
答案 0 :(得分:29)
您必须使dispatch_source_t
类属性或实例变量,因此它不会超出范围(因为在ARC中,当它超出范围时,它会被释放)。如果你这样做,你的代码将正常工作,例如:
@interface ViewController ()
@property (nonatomic, strong) dispatch_source_t timerSource;
@property (getter = isObservingMessages) BOOL observingMessages;
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self startMessaging];
}
- (void)startMessaging
{
self.observingMessages = YES;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
self.timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(self.timerSource, dispatch_walltime(NULL, 0), 2ull * NSEC_PER_SEC, 1ull * NSEC_PER_SEC);
dispatch_source_set_event_handler(self.timerSource, ^{
if (self.isObservingMessages) {
[self observeNewMsgs];
}
});
dispatch_resume(self.timerSource);
}
- (void)observeNewMsgs
{
NSLog(@"JUST TO TEST");
// Staff code...
}
@end
另请注意,如果您希望能够在启动后台进程后更改BOOL
的值,则可能还需要将其设置为类属性,如上所示。我还将其重命名为observingMessages
以使其目的更加明确。
(这只是风格,但我只对表格实例变量使用下划线字符,因此我将_queue
变量重命名为queue
。)