2017-05-08 14 views
1

當處理非常大的數據集(數百萬個項目)時,我的macOS應用程序有時可能需要很長時間才能完成某個操作,有時甚至超過一分鐘。爲了讓用戶知道該應用程序正在工作,我在工具欄中的特殊視圖中顯示像溫度計一樣的進度。這是最初幾年前在優勝美地開發的,在10.9和10.10下運行時仍然可以正常工作。然而,它不適用於塞拉利昂(不確定10.11左右,沒有一個系統來測試它)。NSView顯示代碼在優勝美地工作,但不能在macOS中工作Sierra

以下是這看起來在工作時,表現出30%的進度等。其效果與Xcode中工具欄中顯示的構建過程非常相似(和Xcode一樣,其他信息顯示在橫幅中,這就是爲什麼我不使用NSProgressIndicator)。

Progress Indicator Banner

進度條使用稱爲InfoBannerView類,這是NSButton的子類顯示。下面是這個類的drawRect:方法(繪製背景的非進度代碼,爲了清楚起見,省略了文本)。 progressValue是,可以是0和1之間的屬性,該方法簡單地繪製一個圓角矩形填充視圖的寬度的百分比,如溫度計。

- (void)drawRect:(NSRect)dirtyRect 
{ 
    [super drawRect:dirtyRect]; 

    NSRect bannerRectangle = [self bounds]; 
    { 
     NSColor* progressColor = [NSColor colorFromHexRGBString:@"85ade1"]; 

     ... draw outline and background of banner 

     if (progressValue > 0.0f && progressValue < 1.0f) { 
      [progressColor setFill]; 
      NSRect progressRect = NSInsetRect(bannerRectangle, 1.0, 1.0); 
      CGFloat progressWidth = progressRect.size.width * progressValue; 
      progressRect.size.width = progressWidth; 
      NSBezierPath* roundedProgressPath = [NSBezierPath bezierPathWithRoundedRect:progressRect xRadius:4 yRadius:4]; 
      [roundedProgressPath fill]; 
     } 

     ... draw text on banner 
    } 
} 

這需要較長的時間來運行看起來像這樣的代碼:

for { 

    ... do stuff that takes a long time 

    InfoBannerView * ibv = [windowController recordCountView]; 
    [ibv setProgress:value]; 
    [ibv display]; 
} 

[ibv display]應該立即更新進度標識顯示,無需等待運行的循環。 (注意:出於性能原因,我並不真正每次都通過循環顯示,但爲了清晰起見,我刪除了該代碼。)

如果此代碼在Mac OS X 10.10上運行,它的工作原理完美。工作進行時,進度條逐漸填滿橫幅視圖。

但是,如果這個代碼是在MacOS 10.12塞拉利昂運行,沒有什麼是可見的。我已經確定drawRect:代碼被重複調用,因爲它應該是。它被稱爲正確的對象。所有的尺寸和數值都是正確的。唯一的問題是 - 沒有任何東西。在普通視圖更新過程中調用,但是通過強制progressValue 0.3我確定這些代碼在視圖更新汲取正確也,其實,這就是我做以上說明:(當drawRect中繪製不正常發生。 )

我試着運行與10.10 SDK鏈接的應用程序的舊版本。通過-display調用時仍然沒有繪圖。它只適用於10.10或更早的版本。

我是希望在寫這篇文章的時候,雲會分開,答案會變得明顯,但沒有這樣的運氣。我在10.11或10.12發行說明中沒有看到任何相關內容。也許我在做一些愚蠢的事情,一直都是錯誤的,我只是幸運而已。在這一點上,我沒有想法。

+0

控件是可點擊的按鈕嗎? – Willeke

+0

@Willeke在寫這篇文章時,InfoBannerView是NSButton的一個子類。但是,它並沒有真正使用任何NSButton功能,所以昨晚我將它改爲NSView的子類,以查看NSButton是否是問題。事實並非如此。 (橫幅是可點擊的,點擊在mouseDown:方法中處理。) –

回答

0

從丹尼爾Jalkut上鬆弛部分建議導致了一個解決方案。更換這行:

[ibv display]; 

與此:

[ibv setNeedsDisplay:YES]; 
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0]]; 

導致正確的顯示情況發生,如下圖所示。

enter image description here

我認爲原來的問題可能是在塞拉利昂的錯誤 - 如果-display方法不會立即(它以前做)畫,它是什麼呢?

相關問題