2010-11-19 97 views
3

我有一個簡單的顯示CoreData的UITableView控制器。我試圖實現 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath;和動畫有問題。核心數據存儲被更新,但動畫不起作用。UITableView中的moveRowAtIndexPath導致不正確的動畫

如何讓動畫正確反映發生在覈心數據對象上的變化?

例如:

初始順序:

alt text

項2之後頂端:

alt text

,或者初始訂購:

alt text

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];    
} 

和委託:

移動第1項至第3位後

- (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; 
} 
} 

回答

8

問題是由原因引起的委託人干擾我的重新排序實施。 我在保存我的ManagedObjectContext之前添加了一個bool:

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; 
} 

} 
+0

@glenstory,早上大部分時間都在尋找解決這個問題的方法。感謝您發佈此信息。解決了我的問題呢! – 2011-01-21 19:52:16

+0

不客氣! – glenstorey 2011-01-23 02:02:05

+0

是的,也爲我工作,特別是因爲我的表總是處於編輯模式。 – 2011-11-28 17:31:31

2

我有同樣的問題,我通過將保存代碼移到「保存」位置來解決它。即:

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

我認爲這是可以理解的,事情會被搞砸,如果你保存在移動的東西周圍。而且-(void)setEditing似乎是一個節約的好地方。

順便說一句,感謝指出問題的原因!