[英]Timer inside global queue is not calling in iOS
-(void)viewDidLoad{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[NSTimer scheduledTimerWithTimeInterval:0.10
target:self
selector:@selector(action_Timer)
userInfo:nil
repeats:YES];
}
);
}
-(void)action_Timer{
LOG("Timer called");
}
沒有調用action_Timer
。 我不知道為什么。 你有什么主意嗎?
您正在從GCD工作線程調用+[NSTimer scheduledTimerWithTimeInterval:...]
。 GCD工作線程不運行運行循環。 這就是為什么你的第一次嘗試不起作用的原因。
當您嘗試[[NSRunLoop mainRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode]
,您正在從GCD工作線程向主運行循環發送消息。 NSRunLoop
存在的問題不是線程安全的。 (這在NSRunLoop類參考中有記錄 。)
相反,您需要調度回主隊列,以便在將addTimer:...
消息發送到主運行循環時,它在主線程上完成。
-(void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSTimer *timer = [NSTimer timerWithTimeInterval:0.10
target:self
selector:@selector(action_Timer)
userInfo:nil
repeats:YES];
dispatch_async(dispatch_get_main_queue(), ^{
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
});
});
}
實際上,如果您要在主運行循環中安排計時器,則沒有理由在后台隊列上創建計時器。 您可以調度回主隊列來創建和安排它:
-(void)viewDidLoad {
[super viewDidLoad];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSLog(@"on background queue");
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"on main queue");
[NSTimer scheduledTimerWithTimeInterval:0.10
target:self
selector:@selector(action_Timer)
userInfo:nil
repeats:YES];
});
});
}
請注意,我的兩個解決方案都將計時器添加到主運行循環中,因此計時器的操作將在主線程上運行。 如果您希望計時器的操作在后台隊列上運行,您應該從操作中調度它:
-(void)action_Timer {
// This is called on the main queue, so dispatch to a background queue.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
LOG("Timer called");
});
}
您必須將計時器添加到主運行循環以啟動計時器,但首先,您應該在私有ivar或屬性中保持對計時器的引用:
-(void)viewDidLoad{
// on the main queue
self.mytimer = [NSTimer scheduledTimerWithTimeInterval:0.10
target:self
selector:@selector(action_Timer)
userInfo:nil
repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode];
}
-(void)action_Timer{
dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
LOG("Timer called");
});
}
我發現在被調用的方法中更容易脫離主隊列。 在某些點,也許在viewDidUnlod
或dealloc
,你將調用[self.myTimer invalidate]; self.myTimer = nil;
[self.myTimer invalidate]; self.myTimer = nil;
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.