Filtragem NSTableView baseada em visualização + animação

9

Eu tenho uma visão baseada em NSTableView que às vezes eu filtro usando NSPredicate . Existe alguma maneira de animar os itens sendo removidos / adicionados / reordenados em todo o tableview para ter o mesmo efeito que beginUpdates , endUpdates e insertRowsAtIndexes:withAnimation , etc?

Eu explorei maneiras de filtrar manualmente minha matriz, mas minhas tentativas se mostraram inúteis, então agora estou me perguntando se existe uma maneira melhor (ou integrada) de fazer isso. Eu me perguntei se NSArrayController faz isso automaticamente, mas acho que não.

    
por Alex Zielenski 23.11.2011 в 00:39
fonte

1 resposta

5

Eu mesmo escrevi código para fazer isso - dados os arrays 'before' e 'after', calcule os parâmetros necessários para insertRowsAtIndexPaths: , deleteRowsAtIndexPaths: , etc. O código é um pouco complicado, então provavelmente tem bugs - use a seu critério!

@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

Então você chama assim:

    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];
    
por Bryan 15.09.2012 / 18:59
fonte