2

我想解決Objective-C中的一個問題,但我不認爲這個問題是特定於語言的。模型應該如何更新其進度的UI?

我不得不在一個沒有UI概念的模型類中做一些處理。但是,這個處理需要一些時間,我想通過進度條讓用戶知道狀態。

我在這第一次嘗試定義進度處理協議/接口的概念有一些方法,如

-startOperation; 
-updateProgress:(double)currentValue ofMax:(double)maxValue 
-endOperation; 

這樣我的UI可以實現了模型不一定知道其他發生的事情的細節比有人想要進度更新。目前我的用戶界面取消隱藏進度條,並更新它,然後在完成時隱藏它。到現在爲止還挺好。

但是,事實證明,有時這種操作處理非常快。這樣UI更新在執行時會導致相當令人不安的閃爍。我不知道手術是快速還是緩慢。

我的一個想法是強制操作至少需要一定的時間來避免UI變化如此震撼人心,但這似乎將UI的知識放在模型類中,而這肯定是錯誤的。

這似乎是一個常見的問題(希望)一些已知的模式。

你會如何解決這個問題?

回答

3

可以使用的NSTimer耽誤你的進度條顯示,直到你的操作已經爲給定的時間量運行,說半秒:

-(void)startOperation { 
    // Show the progress bar in 0.5 seconds 
    if (!_timer) { 
     _timer = [[NSTimer scheduledTimerWithTimeInterval:0.5 
                target:self 
               selector:@selector(showProgressBar:) 
               userInfo:nil 
                repeats:NO] retain]; 
    } 
} 

在-endOperation,取消計時器和隱藏進度條:

-(void)endOperation { 
    [_timer invalidate]; // cancel the timer 
    [_timer release]; 
    _timer = nil; 

    [self hideProgressBar]; 
} 

如果該操作在小於0.5秒完成,則將顯示進度條之前定時器被取消。

2

通常所做的一件事就是讓您的進度條實現不立即顯示,並根據第一對更新(或超時)應用一些啓發式來確定它是否需要顯示自己。例如,這就是Java ProgressMonitor的行爲。 (ProgressMonitor是一個很好的抽象,將進度知識與其圖形表示分開)。

一旦顯示進度窗口小部件,您可以在悠閒的計時器上重新繪製一次,比如說每秒10次,而不是用重繪對每個進度更改事件做出反應。

7

喬納森和達倫的回答涵蓋了您的實際問題,但我會在標題中添加一些有關問題的內容:「模型應如何更新其進度的UI?」

答案當然是不應該的。該模型不應該知道任何關於顯示數據的任何協議的任何。應該有一個統一的綁定層負責將信息從模型傳播到接口。幸運的是,可可已經包含了這樣一種綁定機制:鍵值觀察。

你應該做的是定義一個任何模型類的屬性,其中的進展的概念是有道理的,像@property (assign) float progress。那麼你make sure the class is KVO compliant。希望跟蹤進度的控制器代碼只需註冊以觀察此值,如下所示:

[theObject addObserver:self forKeyPath:@「progress」options:0 context:NULL];

請務必閱讀NSKeyValueObserving(KVO)非正式協議的文檔。 另外,您可能想看看Mike Ash的KVO相關注釋和代碼:Key-Value Observing Done Right

+2

A +++++++深刻見解再次超越! –

+1

同意。這是一個偉大的見解。謝謝。 – nall