2010-11-19 15 views
3

CoreDataを表示するシンプルなUITableViewコントローラがあります。私は実装しようとしています - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath;アニメーションに問題があります。コアデータストアは更新されますが、アニメーションは機能しません。UITableViewのmoveRowAtIndexPathが不正なアニメーションを引き起こす

コアデータオブジェクトに発生した変更をアニメーションに正しく反映させるにはどうすればよいですか?

初期順序:

alt text

項目2の後上部に:

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

とデリゲート:ここalt text

に関連するコードは次のとおり

位置3にアイテム1を移動させた後

- (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関数のいずれかをスキップするために使用します。最適なソリューションではありませんが、この実装では機能します。なぜこのようなことが起こったのかを説明するコメント/回答は感謝しています。

/** 
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は、この問題の解決策のためにほとんどの朝を検索していました。これを投稿していただきありがとうございます。私の問題も解決しました! –

+0

あなたは大歓迎です! – glenstorey

+0

私のテーブルは常に編集モードになっているので、特に私のために働いた。 –

2

私は同じ問題がありましたが、保存コードを「保存」場所に移動して修正しました。すなわち:

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

私はそれはあなたの周りのものを移動する途中で保存する場合は、物事がめちゃめちゃにされるだろうことは理解だと思います。 -(void)setEditingは節約をするのに適しているようです。

btw、問題の原因を指摘してくれてありがとう!

関連する問題