Обновление анимации данных (мягкое удаление) в Core Data / UITableView - PullRequest
3 голосов
/ 06 мая 2011

У меня есть табличное представление, которое поддерживается fetchedResultsController. В ячейках таблицы у меня есть кнопка, которая выполняет мягкое удаление, если это касается представления ... нажмите кнопку, вызывается селектор, который выполняет мягкое удаление, и ... что-то должно произойти (я я много чего пробовал), но ничего из того, что я пробовал, не оживляет анимацию строк Apple.

Я могу выполнять простые анимации строк, например, заставляя их скользить по сторонам (оставляя пустую строку до тех пор, пока я не скажу таблице перезагрузиться, что, в свою очередь, немного раздражает) Это самое близкое, что я пришел:

 -(void) completeTask: (id) sender {
     NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[[sender superview] superview]];

     NSDate *date = [[NSDate alloc] init];
     NSManagedObject *task = [self.fetchedResultsController objectAtIndexPath:indexPath];

     [task setValue:date forKey:@"complete"];

     AppController *ac = [AppController sharedAppController];
     NSManagedObjectContext *moc = [ac managedObjectContext];

     NSError *error = nil;
     if(![moc save:&error]){
         NSLog(@"%@ %@",error, [error description]);
         exit(-1);
     } else {
         UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];

         CGRect cellFrame = cell.frame;
         [UIView beginAnimations:nil context:nil];
         [UIView setAnimationDuration:0.35];
         [UIView setAnimationDelegate:self];
         [UIView setAnimationDidStopSelector:@selector(someAnimationDidStop:finished:context:)];
         cell.frame = CGRectMake(cellFrame.size.width , cellFrame.origin.y, cellFrame.size.width, cellFrame.size.height);
         [UIView commitAnimations];
     }
 }

-(void) someAnimationDidStop:(NSString *)animationID 
                    finished:(BOOL)finished context:(void *)duration {
    NSLog(@"Animation Stopped");
    [self fetchResults]; // this guy performs a new fetch and table data reload
}

Я чувствую, что нахожусь на правильном пути, однако я не думаю, что это действительно довольно ответ. Я надеялся, что каким-то образом controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: будет ответом. Я предполагаю, что если мне нужны стандартные анимации Apple, мне нужно будет создать отдельный NSMutableArray, чтобы отслеживать результаты и просто убедиться, что он синхронизирован.

Мысли и мнения?

Спасибо !!!

Ответы [ 2 ]

2 голосов
/ 07 мая 2011

Полагаю, у вас уже есть предикат для NSFetchedResultsController, который не извлекает эти "мягко удаленные" объекты.

Таким образом, теоретически все, что вам нужно сделать, это реализовать все NSFetchResultsControllerDelegate методов. Пример реализации из документации будет работать нормально.
Не забудьте установить delegate из NSFetchedResultsController

Затем вместо ручного управления ячейками просто измените значение «мягкого удаления» из объекта. NSFetchResultsController будет контролировать контекст, он выясняет, что это изменение заставит объект исчезнуть из коллекции, поэтому он удалит ячейку из tableView.

1 голос
/ 06 мая 2011

РЕДАКТИРОВАТЬ: @fluchtpunkt ответ правильный.После внесения еще нескольких обновлений в мой код мое решение снова сломалось.Удаление блока, который повторно выбирает FRC, заставило все это работать снова.


Я удивлен, что я не понял этого во всех моих повторяющихся тестах (обучении) вчера.У меня были проблемы с синхронизацией результатов выборки основных данных с табличным представлением хорошим способом - часто я получал индекс несоответствия (бла-бла-бла, число строк (#) должно равняться числу # плюс илиминус количество строк бла-бла-бла (0 вставлено: # удалено) .. и т. д.).

Для этого выполните следующие шаги:

  1. Выполните мягкое удаление и сохранение
  2. установить контроллер извлеченных результатов на nil self.fetchedrResultsController = nil
  3. Выполнить новую выборку
  4. ТО, удалить строку из таблицы:
self.fetchedResultsController = nil;
         NSError *error = nil;
         if (![[self fetchedResultsController] performFetch:&error]) {
             NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
             abort();
         } else {
             [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
         }

Я действительно не знаю, почему я не понял этого раньше, но это имеет такой смысл.Свежие глаза?

Вот полная картина:

 -(void) completeTask: (id) sender {

     NSIndexPath *indexPath = [self.tableView indexPathForCell:(UITableViewCell *)[[sender superview] superview]];

     NSManagedObject *task = [self.fetchedResultsController objectAtIndexPath:indexPath];

     [task setValue:date forKey:@"complete"];

     AppController *ac = [AppController sharedAppController];
     NSManagedObjectContext *moc = [ac managedObjectContext];

     NSError *error = nil;
     if(![moc save:&error]){
         NSLog(@"Uh oh - couldn't save the delete! %@ \n%@",error, [error description]);
         exit(-1);
     } else {

         // Save successful; re-fetch data (background)
         self.fetchedResultsController = nil;
         NSError *error = nil;
         if (![[self fetchedResultsController] performFetch:&error]) {
             NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
             abort();
         } else {
             //update the table view with row animation
             [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
                                   withRowAnimation:UITableViewRowAnimationRight];
         }
     }
 }
...