2011-05-03 67 views
0

我的應用程序的UI類似於Phone.app-> Latest:UITableView和導航欄中的UISegmentedControl。我想要做的是在選擇第一部分的情況下顯示全套數據,如果選擇了第二部分,則顯示過濾的數據集。過濾分段UITableView

當用戶選擇UISegmentedControl中的第二項時,我從表視圖中刪除特定的行。這裏是代碼:

[tableView beginUpdates]; 
NSMutableArray *indexPaths = [NSMutableArray array]; 
/// ... fill up indexPaths with row indexes 
[tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade]; 
[tableView endUpdates]; 

上面的代碼工作正常,除了一個嚴重的問題:性能。刪除2200行中的1500個大約需要20秒。這顯然是不可接受的。用動畫過濾表格視圖行的最佳方法是什麼?

回答

1

對於大的變化,以您的數據源,所以建議您使用

[tableView reloadData] 

,而不是

[tableView beginUpdates]; 
// changes here .... 
[tableView endUpdates]; 

編輯:我還沒有嘗試過這種方法我自己,但考慮改變只有那些包含在可見單元集合中的​​行,可能是上面和下面的緩衝區。你可以通過調用

[tableView indexPathsForVisibleRows]; 
+0

iOS SDK文檔是否指定了建議的最大值在beginUpdates和endUpdates之間刪除/插入的行是否保持動畫順暢? – sgosha 2011-05-03 19:56:04

+0

不是我知道關閉,但reloadData只關注表視圖中的可見單元格,這使得它更快。我相信你可以嘗試確切的數量,但它很可能會低於1500 – nduplessis 2011-05-03 20:06:43

0

如何使用兩個數組?其中一個是完整的數據集,另一個是已過濾的數據集。

這樣你可以有兩個不同的tableview,並且根據選定的段是什麼,你可以在兩個tableview之間做一個淡入淡出的動畫。例如,假設你選擇一個領域:

-(void)switchTableViews 
{ 
    [UIView beginAnimations:nil context:NULL]; 
    [UIView setAnimationBeginsFromCurrentState:YES]; 
    [UIView setAnimationCurve:UIViewAnimationCurveLinear]; 
    [UIView setAnimationDuration:0.5]; 
    [UIView setAnimationDidStopSelector:@selector(hideTableView)]; 

    switch (segmentedControl.selectedSegmentIndex) 
    { 
     case 0: 
     { 
     tableView1.alpha = 1.0; 
     tableView2.alpha = 0.0; 
     } 
     break; 
     case 1: 
     { 
     tableView1.alpha = 0.0; 
     tableView2.alpha = 1.0; 
     } 
     break; 
     default: 
     break; 
    } 

    [UIView commitAnimations]; 
} 

- (void)hideTableView 
{ 
    switch (segmentedControl.selectedSegmentIndex) 
    { 
     case 0: 
     { 
     tableView1.hidden = NO; 
     tableView2.hidden = YES; 
     } 
     break; 
     case 1: 
     { 
     tableView1.hidden = YES; 
     tableView2.hidden = NO; 
     } 
     break; 
     default: 
     break; 
    } 
} 

當然,這將意味着對數據源的方法,建立不同的代碼集,但它並不像你想象的那麼難。只需使用一個簡單的if-else來檢查正在設置哪個tableview。

+0

是的,它不會是很難做到的。但是您建議的解決方案不會使行向上滑動以代替被刪除的行 - 它只是從一個視圖到另一個視圖的過渡。請前往手機 - >最新,並嘗試在'全部'和'錯過'之間切換,看看我想在我的應用中看到什麼樣的動畫。 – sgosha 2011-05-03 19:48:37

+0

好吧,我想不出你想要什麼替代方案來處理性能問題對不起:(你真的需要一次顯示2000行嗎?你能不能實現分頁(一個「加載更多」的最後一個單元格在tableview中增加了100多行),這樣不但可以幫助執行刪除行的性能,還可以渲染tableview。除此之外,我認爲我無法提供解決方案:( – Sid 2011-05-03 19:57:28

0

我絕對@nduplessis同意,你應該重新加載數據源,而不是操縱視圖獲取可見單元格的indexPaths。我提出了一個解決方案,similar question here確實會導致你的行向上滑動。

基本的想法是調用reloadSections:withRowAnimation:並在你的UITableViewDataSource方法中切換分段控件的selectedSegmentIndex。

假設你的數據是平的(只有一節),這將是這個樣子:

- (IBAction)segmentSwitch:(id)sender 
{ 
    [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    switch (self.segmentedControl.selectedSegmentIndex) 
    { 
     default: 
     case 0: 
      return [self.allRows count]; 
     case 1: 
      return [self.onlySomeRows count]; 
    } 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    id data; 
    switch (self.segmentedControl.selectedSegmentIndex) 
    { 
     default: 
     case 0: 
      data = [self.allRows objectAtIndex:[indexPath row]]; 
      break; 
     case 1: 
      data = [self.onlySomeRows objectAtIndex:[indexPath row]]; 
      break; 
    } 

    //TODO: use data to populate and return a UITableViewCell... 
}