2011-11-22 48 views
9

我有一個基於NSTableView的視圖,我有時會使用NSPredicate進行過濾。是否有任何方法來動畫整個tableview被刪除/添加/重新排序的項目,以產生與beginUpdatesendUpdatesinsertRowsAtIndexes:withAnimation等相同的效果?基於視圖的NSTableView過濾+動畫

我已經探索過諸如手動過濾我的數組等方式,但我的嘗試被證明是徒勞的,所以現在我想知道是否有更好的(或內置的方式)來做到這一點。我想知道是否NSArrayController自動執行此操作,但我不認爲它確實如此。

+2

沒有什麼內置的,我怕 - 很遺憾。 –

+0

NSCollectionView支持這個開箱即用! – bijan

+0

我見過的最接近的是基於單元格的表格:http://www.mactech.com/articles/mactech/Vol.18/18.11/1811TableTechniques/index.html – sbooth

回答

5

我已經編寫了自己做的代碼 - 給出'之前'和'之後'數組,計算所需的參數爲insertRowsAtIndexPaths:deleteRowsAtIndexPaths:等。代碼有點煩瑣,所以可能有錯誤 - 根據您的判斷使用!

@interface NSArray (ArrayDifference) 
    - (void) computeDifferenceTo:(NSArray *)newArray returningAdded:(NSMutableArray **)rowsAdded andDeleted:(NSMutableArray **)rowsDeleted; 
@end 

@implementation NSArray (ArrayDifference) 

// Given two arrays that are expected have items added or removed but not re-ordered, compute the differences 
// in a way usable for UITable insertRows and deleteRows 
- (void) computeDifferenceTo:(NSArray *)newArray returningAdded:(NSMutableArray **)rowsAdded andDeleted:(NSMutableArray **)rowsDeleted 
{ 
    NSArray *oldArray = self; 
    *rowsAdded = [[[NSMutableArray alloc] init] autorelease]; 
    *rowsDeleted = [[[NSMutableArray alloc] init] autorelease]; 

    NSUInteger oldCount = [oldArray count]; 
    NSUInteger newCount = [newArray count]; 
    // Step through the two arrays 
    NSInteger oldIndex = 0, newIndex=0; 
    for (; newIndex < newCount && oldIndex < oldCount;) 
    { 
    id newItem = [newArray objectAtIndex:newIndex]; 
    id oldItem = [oldArray objectAtIndex:oldIndex]; 
    // If the two objects match, we step forward on both sides 
    if (newItem == oldItem) { 
     ++newIndex; 
     ++oldIndex; 
    } 
    else { 
     // Look for the old item to appear later in the new array, which would mean we have to add the rows in between 
     NSRange range = { newIndex+1, newCount - newIndex-1 }; 
     NSUInteger foundIndex = [newArray indexOfObject:oldItem inRange:range]; 
     if (foundIndex != NSNotFound) 
      for (; newIndex < foundIndex; ++newIndex) 
       [*rowsAdded addObject:[NSIndexPath indexPathForRow:newIndex inSection:0]]; 
     else { 
      // Look for the new item to appear later in the old array, which would mean we have to remove the rows in between 
      NSRange range = { oldIndex+1, oldCount - oldIndex-1 }; 
      NSUInteger foundIndex = [oldArray indexOfObject:newItem inRange:range]; 
      if (foundIndex != NSNotFound) 
       for (; oldIndex < foundIndex; ++oldIndex) 
        [*rowsDeleted addObject:[NSIndexPath indexPathForRow:oldIndex inSection:0]]; 
      else { 
       // Old item must be removed and new item added, then we carry on 
       [*rowsAdded addObject:[NSIndexPath indexPathForRow:newIndex++ inSection:0]]; 
       [*rowsDeleted addObject:[NSIndexPath indexPathForRow:oldIndex++ inSection:0]]; 
      } 
     } 
    } 
    } 
    // Once the loop is finished, add in what's left in the new array and remove what is left in the old array 
    for (; newIndex < newCount; ++newIndex) 
    [*rowsAdded addObject:[NSIndexPath indexPathForRow:newIndex inSection:0]]; 
    for (; oldIndex < oldCount; ++oldIndex) 
    [*rowsDeleted addObject:[NSIndexPath indexPathForRow:oldIndex inSection:0]]; 
} 

@end 

然後調用它像這樣:

NSMutableArray *rowsAdded=nil, *rowsDeleted=nil; 
    [myArray computeDifferenceTo:newArray returningAdded:&rowsAdded andDeleted:&rowsDeleted]; 
    [myTableView beginUpdates]; 
    [myTableView insertRowsAtIndexPaths:rowsAdded withRowAnimation:UITableViewRowAnimationBottom]; 
    [myTableView deleteRowsAtIndexPaths:rowsDeleted withRowAnimation:UITableViewRowAnimationFade]; 
    [myTableView endUpdates]; 
相關問題