2014-01-15 28 views
4

我想說明的MBProgressHUD項目的進展情況,但是當我通過靶向這種方法:如何使用GCD演示背景任務?

- (IBAction)signInBttn:(id)sender { 

    MBProgressHUD *hudd = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; 
    hudd.mode = MBProgressHUDModeAnnularDeterminate; 
    hudd.labelText = @"Loading"; 

    __block float value = 0; 
    for (int j = 0; j<2000; j++) { 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

      for (int i = 0; i<20000 ; i++) { 

      } 
      value += 0.001; 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       hudd.progress = value; 
      }); 

     }); 
    }   
} 

HUD完全出現100%。這僅僅是爲了我的信息,我不知道如何創建後臺任務來計算某些事情,以及當他完成後, 40%的HUD令人耳目一新,達到了40%的進步。我希望我自己清楚,如果有人有時間來幫助改進我的代碼,非常感謝任何答案

+0

相同的基本問題,因爲[動態更新一個UILabel(http://stackoverflow.com/q/6336991/)的UI沒有得到重新繪製,直到控制權返回到運行循環。正確的做法是使用某種計時器。 –

+0

空的'for'循環應該是「暫停」嗎?編譯器很可能會優化這種不存在的權利。 –

+0

是的,我想以簡單的方式模擬高級計算 – user3163231

回答

3

在這種情況下,你可以從你的HUD在你的UI更新解耦計數器的更新解決的問題。 Apple在WWDC 2012視頻Asynchronous Design Patterns with Blocks, GCD, and XPC中將此稱爲「異步更新狀態」。

通常這不是必需的(大部分時間,我們正在異步做的事情足夠慢,我們沒有問題),但是如果做的事情比UI運行速度更快,希望能跟上與此同時,您爲此創建了一個「調度源」。我打算用UIProgressView來說明,但同樣適用於幾乎任何UI:

// create source for which we'll be incrementing a counter, 
// and tell it to run the event handler in the main loop 
// (because we're going to be updating the UI) 

dispatch_source_t source = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue()); 

// specify what you want the even handler to do (i.e. update the HUD or progress bar) 

dispatch_source_set_event_handler(source, ^{ 
    self.iterations += dispatch_source_get_data(source); 
    [self.progressView setProgress: (float) self.iterations/kMaxIterations]; 
}); 

// start the dispatch source 

dispatch_resume(source); 

// now, initiate the process that will update the source 

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 

    for (long i = 0; i < kMaxIterations; i++) 
    { 
     // presumably, do something meaningful here 

     // now increment counter (and the event handler will take care of the UI) 

     dispatch_source_merge_data(source, 1); 
    } 

    // when all done, cancel the dispatch source 

    dispatch_source_cancel(source); 
}); 

在我的例子,iterations只是一個long屬性:

@property (nonatomic) long iterations; 

我定義我的kMaxIterations常數如下:

static long const kMaxIterations = 10000000l; 
0

首先,如果您想延遲執行,請使用dispatch_after:Apple Doc,因爲可能是Clang是優化你的循環(即通過使它不存在)。

在該塊內調用主線程上的dispatch_sync來更新UI,因爲dispatch_async不保證「均勻」執行。像這樣的東西應該工作...

for (...) { 
    dispatch_after(<some formula of i>, DEFAULT_PRIORITY, ^{ 
     dispatch_sync(MAIN_QUEUE, ^{ hudd.progress = value }); 
    } 
} 
+0

使用'dispatch_sync'工作,但將後臺進程的速度限制在UI更新發生的速度。 – Rob