2009-07-29 69 views
1

我有一個分段控制被用作切換。當切換時,我在表格視圖中切換了一堆內容,這些內容佔用了很少但很明顯的時間(插入/刪除表格視圖中的部分,動畫更改等)。我希望分段控制立即響應選擇。所以在我的行動處理代碼分段控制的UIControlEventValueChanged事件,我做了以下內容:保持一個UISegmentedControl(等)響應

- (IBAction)groupingChanged:(id)sender { 
    UISegmentedControl *seg = sender; 
    [tableModel toggleOn:[seg selectedSegmentIndex] == ToggleOnIndex]; 
    [self performSelectorOnMainThread:@selector(updateGrouping) 
          withObject:nil 
         waitUntilDone:NO]; 
} 

其中updateGrouping是:

- (void)updateGrouping { 
    MXAssertMainThread(); 

    [tableView beginUpdates]; 
    ... several table updates 
    [tableView endUpdates]; 
} 

設置waitUntilDone:NO允許groupingChanged方法來完成updateGrouping被調用之前,但這似乎不足以重新繪製視圖。分段控制一直持續到表完成更新,然後切換。

於是,我就修改groupingChanged:創建一個線程,像這樣的更新:

- (void)delayed { 
    [self performSelectorOnMainThread:@selector(updateGrouping) 
          withObject:nil 
         waitUntilDone:NO]; 
} 

- (IBAction)groupingChanged:(id)sender { 
    UISegmentedControl *seg = sender; 
    [tableModel toggleOn:[seg selectedSegmentIndex] == ToggleOnIndex]; 
    [self performSelectorInBackground:@selector(delayed) withObject:nil]; 
} 

這確實工作。分段控制立即切換,表格隨即顯示。但我對結果一點都不信任。這只是在新線程啓動時給主線程一個暫緩的副作用嗎?這只是我需要如何排隊更新到用戶界面?這顯然很不好。我希望有人在這種情況下有更好的模式。

回答

1

如果你只是想確保分段控制真正快速重新繪製,我可能不會潛入線程。

相反,我只是設置一個像0.1這樣的低值的計時器,並且應該足以讓控制更新,而不會對用戶造成任何明顯的延遲。

當我有很多工作要做但需要快速的UI更新時,我已經使用了這個。

還是有點「黑客」,但沒有引入線程。

所以......

- (IBAction)groupingChanged:(id)sender { 
    UISegmentedControl *seg = sender; 
    [tableModel toggleOn:[seg selectedSegmentIndex] == ToggleOnIndex]; 
    [NSTimer scheduledTimerWithTimeInterval:0.1 
            target:self 
            selector:@selector(updateGrouping) 
            userInfo:nil 
            repeats:NO];  

} 
+0

這消除了臨時線程,所以這是一個改進,但我拒絕相信沒有常見的非hacky模式。 – 2009-07-29 17:54:18

2

認爲它這樣 - 你所做的一切通常做在主線程,包括用戶界面的更新。

因此,在您的原始代碼中,更新表視圖的代碼在對該段進行了UI更新的代碼之前已達到。

因此,您給予主線程一箇中斷允許更多時間完成UI更新是正確的,因爲主線程被允許在後臺線程處理表更新時完成UI更新。

另一種可以嘗試的方法是使用performSelector:withObject:afterDelay,延遲時間爲0.0(這允許主線程在繼續選擇器之前處理其他事情)。它可能在performSelectorOnMainThread沒有的地方工作,因爲即使它們最終做了非常相似的事情,它也可能更直接。

0

我遇到了同樣的問題,並通過繼承UISegmentedControl來創建Delayed UISegmentedControl來解決此問題。

在延遲控制中,我覆蓋了addTarget:action:forControlEvents:以捕獲目標&的操作。然後,當發生段事件時,我運行NSTimer以在設置的延遲後啓動捕獲的目標&操作。其結果是,在UI被更新,以顯示該段點擊,我可以使用DelayedUISegmentedControl就像我會一個UISegmentedControl:

// Follows all normal initialization patterns of UISegmentedControl 
UISegmentedControl *segmentedControl = [[DelayedUISegmentedControl alloc] 
    initWithItems:[NSArray arrayWithObjects: @"First", @"Second", nil]]; 

// Adds a delay to the selector; default is 0.25 
[segmentedControl addTarget:self action:@selector(segmentAction:) 
    forControlEvents:UIControlEventValueChanged]; 

如果你想下載我已經開源了它google code控制。