moveRowAtIndexPath в UITableView вызывает некорректную анимацию - PullRequest
3 голосов
/ 20 ноября 2010

У меня есть простой контроллер UITableView, который показывает CoreData. Я пытаюсь реализовать - (void) tableView: (UITableView *) tableView moveRowAtIndexPath: (NSIndexPath *) и возникли проблемы с анимацией. Базовое хранилище данных обновляется, но анимация не работает.

Как я могу заставить анимацию правильно отражать изменения, которые происходят с основными объектами данных?

Например:

Первоначальный заказ:

alt text

После пункта 2 наверх:

alt text

или, начальный заказ:

alt text

После перемещения элемента 1 в положение 3:

alt text

Вот соответствующий код:

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
//this implementation is from this tutorial: http://www.cimgf.com/2010/06/05/re-ordering-nsfetchedresultscontroller/
NSMutableArray *things = [[fetchedResultsController fetchedObjects] mutableCopy];

// Grab the item we're moving.
NSManagedObject *thing = [fetchedResultsController objectAtIndexPath:fromIndexPath];

// Remove the object we're moving from the array.
[things removeObject:thing];
// Now re-insert it at the destination.
[things insertObject:thing atIndex:[toIndexPath row]];

// All of the objects are now in their correct order. Update each
// object's displayOrder field by iterating through the array.


int i = 0;
for (NSManagedObject *mo in things)
{
    [mo setValue:[NSNumber numberWithInt:i++] forKey:@"order"];
}


NSLog(@"things: %@", things);
[things release], things = nil; 

[managedObjectContext save:nil];            
}

и делегат:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
NSLog(@"didChangeObject:");
UITableView *tableView = self.tableView;

switch(type) {
    case NSFetchedResultsChangeInsert:
        NSLog(@"ResultsChangeInsert:");
        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeDelete:
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;

    case NSFetchedResultsChangeMove:
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
        [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
        break;
}
}

Ответы [ 2 ]

8 голосов
/ 21 ноября 2010

Проблема была вызвана тем, что делегат вмешался в мою реализацию переупорядочения.Я добавил bool перед сохранением моего ManagedObjectContext:

reordering = YES;[managedObjectContext save: nil];

и использовал его для пропуска любой из функций делегата FetchedResultsController.Не лучшее решение, но оно работает для этой реализации.Буду благодарен за любые комментарии / ответы, объясняющие, почему это произошло.

/**
Delegate methods of NSFetchedResultsController to respond to additions, removals and so  on.
*/

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {

if (!reordering) {

// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
NSLog(@"controllerWillChangeContent:");

[self.tableView beginUpdates];

}

}


- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
if (!reordering) {

    NSLog(@"didChangeObject:");
    UITableView *tableView = self.tableView;

    switch(type) {
        case NSFetchedResultsChangeInsert:
            NSLog(@"ResultsChangeInsert:");
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;

        /*case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;*/
    }

}
}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
if (!reordering) {

    NSLog(@"didChangeSelection:");
    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
if (!reordering) {

    NSLog(@"didChangeContent:");
    // The fetch controller has sent all current change notifications, so tell the table view to process all updates.
    [self.tableView endUpdates];
}else {
    reordering = NO;
}

}
2 голосов
/ 30 декабря 2011

У меня была такая же проблема, и я исправил ее, переместив код сохранения в место "сохранения" i.e.:

- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
    [super setEditing:editing animated:animated];
    if (!editing) {
        //save here
    }
}

Я думаю, понятно, что все будет испорчено, если вы сэкономите в процессе перемещения. И -(void)setEditing кажется хорошим местом для экономии.

Кстати, спасибо, что указали причину проблемы!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...