我試圖在包含單個進度欄的窗口上顯示工作表,以顯示使用Grand Central Dispatch異步運行的一些長函數的進度。我幾乎已經知道了,但無法讓工作表看起來很專注,可能是因爲我沒有使用runModalForWindow:
或類似工具。如何在使用Grand Central Dispatch處理某些內容時正確顯示「進度」表格?
這大約是我目前做的事情,它發生的主窗口中按下按鈕的結果:
// Prepare sheet and show it...
[NSApp beginSheet:progressSheet modalForWindow:window modalDelegate:nil didEndSelector:NULL contextInfo:NULL];
[progressSheet makeKeyAndOrderFront:self];
[progressBar setIndeterminate:NO];
[progressBar setDoubleValue:0.f];
[progressBar startAnimation:self];
// Start computation using GCD...
dispatch_async(dispatch_get_global_queue(0, 0), ^{
for (int i = 0; i < 1000; i ++) {
// Do some large computation here
// ...
// Update the progress bar which is in the sheet:
dispatch_async(dispatch_get_main_queue(), ^{
[progressBar setDoubleValue:(double)i];
});
}
// Calculation finished, remove sheet on main thread
dispatch_async(dispatch_get_main_queue(), ^{
[progressBar setIndeterminate:YES];
[NSApp endSheet:progressSheet];
[progressSheet orderOut:self];
});
});
這工作,除主窗口仍然是重點,表格沒有對焦,並且進度條不動畫(除非我使用setUsesThreadedAnimation:YES
)。
我想我遇到的問題是我不確定如何在啓動異步計算之前在不阻止主線程的情況下以模態方式運行表單。
爲窗口模態地運行工作表不應該阻塞主線程(否則在方法開始處的'-beginSheet:'位後沒有任何內容會被執行)。我在我的應用程序中使用了幾乎與此相同的東西(模態表單,帶有進度條),它在後臺運行的GCD塊中更新得很好。工作表滑下的窗口上的控件呈灰色,表示窗口已失去焦點,因此看起來也很正常。有沒有其他的東西在主線程上排隊呢? –
@BradLarson我能想到的唯一另外一件事情可能會導致問題,就是'dispatch_apply'作爲主要計算的一部分,但是用標準循環替換它並沒有什麼區別。否則,主線程上幾乎沒有其他的東西在運行。我仍然可以主要與主窗口上的控件在表單後面交互,並且它們仍然顯示爲焦點(即不顯示灰色)。例如,在顯示錶單時,主窗口上的文本框會顯示對焦環,我仍然可以在其中輸入文本(儘管我無法使用鼠標選擇文本)。 – Robert