我想創建這樣一個循環:dispatch_after循環/重複
while (TRUE){
dispatch_after(...{
<some action>
});
}
一個viewDidLoad中之後。這個想法是重複dispatch_after。 dispatch_after在執行操作之前等待兩秒鐘。
這不起作用 - 屏幕只是空白?它陷入循環還是...?
我想創建這樣一個循環:dispatch_after循環/重複
while (TRUE){
dispatch_after(...{
<some action>
});
}
一個viewDidLoad中之後。這個想法是重複dispatch_after。 dispatch_after在執行操作之前等待兩秒鐘。
這不起作用 - 屏幕只是空白?它陷入循環還是...?
無論計劃何時運行,dispatch_after(...)
調用都會立即返回。這意味着你的循環在調度它們之間不會等待兩秒鐘。相反,你正在構建一個無限的隊列,這些隊列將從現在開始兩秒鐘發生,而不是彼此之間的兩秒鐘。
所以是的,你被困在一個無限循環中,要添加越來越多的塊來執行。如果你想要每兩秒鐘發生一次,那麼你可以使用一個重複的NSTimer或者在其內部有dispatch_after塊(以便第二個塊在第一個塊之後運行兩秒鐘)。
大衛,你有一個使用[NSTimer(https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/ nstimer_Class/Reference/NSTimer.html)]的方式,我想使用它?我猜while循環可以保持原狀?像 +(NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)秒調用:(NSInvocation *)調用重複:(BOOL)重複也許? – Roel 2012-07-13 06:23:39
如果您有重複計時器,則不需要循環。計時器每兩秒鐘自動啓動一次,只需啓動一次。 – 2012-07-13 06:28:01
所以但NSTimer去哪裏 - 我仍然可以把它放在viewDidLoad中嗎? – Roel 2012-07-13 06:34:22
是的,你可以用gcd來做到這一點。儘管你需要兩個額外的c函數。
static void dispatch_async_repeated_internal(dispatch_time_t firstPopTime, double intervalInSeconds, dispatch_queue_t queue, void(^work)(BOOL *stop))
{
__block BOOL shouldStop = NO;
dispatch_time_t nextPopTime = dispatch_time(firstPopTime, (int64_t)(intervalInSeconds * NSEC_PER_SEC));
dispatch_after(nextPopTime, queue, ^{
work(&shouldStop);
if(!shouldStop)
{
dispatch_async_repeated_internal(nextPopTime, intervalInSeconds, queue, work);
}
});
}
void dispatch_async_repeated(double intervalInSeconds, dispatch_queue_t queue, void(^work)(BOOL *stop))
{
dispatch_time_t firstPopTime = dispatch_time(DISPATCH_TIME_NOW, intervalInSeconds * NSEC_PER_SEC);
dispatch_async_repeated_internal(firstPopTime, intervalInSeconds, queue, work);
}
經過測試!按預期工作。
GCD已經得到了這個建於
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
if (timer)
{
dispatch_source_set_timer(timer, dispatch_time(DISPATCH_TIME_NOW, interval * NSEC_PER_SEC), interval * NSEC_PER_SEC, (1ull * NSEC_PER_SEC)/10);
dispatch_source_set_event_handler(timer, block);
dispatch_resume(timer);
}
Imho這是最好的答案。 'dispatch_source_cancel()'可以用來取消定時器。詳細信息 - http://stackoverflow.com/a/14591070/2151614 – Zmey 2016-08-04 13:02:30
如果您想異步任務的延遲後運行檢查,例如,如果一個標籤已經更新,然後完成,你可以使用下面的代碼:
typedef void (^RepeatCompletionHandler)(BOOL isRepeat);
typedef void (^RepeatBlock)(RepeatCompletionHandler completionHandler);
- (void)dispatchRepeat:(int)seconds withBlock:(RepeatBlock)block {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, seconds * NSEC_PER_SEC),
dispatch_get_main_queue(), ^() {
block(^(BOOL isRepeat) {
if (isRepeat) {
return [self dispatchRepeat:seconds withBlock:block];
}
});
});
}
例如:
[self dispatchRepeat:5 withBlock:^(RepeatCompletionHandler completionHandler) {
[tagsService getTagValueForTagName:TagName value:^(NSString *tagValue) {
if (![TagValue isEqualToString:tagValue]) {
return completionHandler(YES);
}
completionHandler(NO);
}];
}];
謝謝..它的工作。 :) – 2016-06-07 06:06:03
......或者你沒有意識到dispatch_after是異步的。 – 2012-07-13 06:18:44
我慢慢開始意識到這樣:) – Roel 2012-07-13 06:20:21