我想在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,_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... }
那么这是什么问题?如何解决这个问题?
解决方法
您必须使您的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,queue); dispatch_source_set_timer(self.timerSource,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的值,您可能也希望将其设置为类属性,如上所示.我也将其更名为观察消息,使其目的更为简单.
(它只是风格,但我只使用下划线字符的类实例变量,所以我将你的_queue变量重命名为队列.)