當處理非常大的數據集(數百萬個項目)時,我的macOS應用程序有時可能需要很長時間才能完成某個操作,有時甚至超過一分鐘。爲了讓用戶知道該應用程序正在工作,我在工具欄中的特殊視圖中顯示像溫度計一樣的進度。這是最初幾年前在優勝美地開發的,在10.9和10.10下運行時仍然可以正常工作。然而,它不適用於塞拉利昂(不確定10.11左右,沒有一個系統來測試它)。NSView顯示代碼在優勝美地工作,但不能在macOS中工作Sierra
以下是這看起來在工作時,表現出30%的進度等。其效果與Xcode中工具欄中顯示的構建過程非常相似(和Xcode一樣,其他信息顯示在橫幅中,這就是爲什麼我不使用NSProgressIndicator)。
進度條使用稱爲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發行說明中沒有看到任何相關內容。也許我在做一些愚蠢的事情,一直都是錯誤的,我只是幸運而已。在這一點上,我沒有想法。
控件是可點擊的按鈕嗎? – Willeke
@Willeke在寫這篇文章時,InfoBannerView是NSButton的一個子類。但是,它並沒有真正使用任何NSButton功能,所以昨晚我將它改爲NSView的子類,以查看NSButton是否是問題。事實並非如此。 (橫幅是可點擊的,點擊在mouseDown:方法中處理。) –