NSFetchedResultsController
何十回も一緒に仕事をしてきましたが、原因が見つからないように見える問題に遭遇しました。
テーブル ビューのデータ ソースを管理する がありますUIViewController
。NSFetchedResultsController
でオブジェクトを削除するたびにNSFetchedResultsController
、フェッチされた結果コントローラーによってテーブル ビューが更新されますが、NSManagedObjectContext
(削除をコミットするために) を保存すると、削除されたばかりのオブジェクトに対して挿入がトリガーされます。最終的な結果として、オブジェクトはテーブル ビューから削除されません。
奇妙なことに、アプリケーションを再起動すると、削除されるはずだったオブジェクトが実際にはストアから削除され、テーブル ビューに表示されません。
明確にするために、メイン スレッドでのみアクセスされるマネージド オブジェクト コンテキストを 1 つだけ使用します。つまり、セットアップは非常に簡単です。
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Fetch Store
CCDStore *store = [self.fetchedResultsController objectAtIndexPath:indexPath];
// Delete Store
[self.fetchedResultsController.managedObjectContext deleteObject:store];
// Save Changes
NSError *error = nil;
[self.fetchedResultsController.managedObjectContext save:&error];
if (error) {
NSLog(@"Error %@ with user info %@.", error, error.userInfo);
}
}
}
削除されたオブジェクトが fetched results コントローラーに挿入されるのにオブジェクトが fault になるのですが、そもそもなぜそれが fetched results コントローラーに追加されるのかわかりません。
例外やエラーはスローされません。isDeleted
オブジェクトに対してandを呼び出しvalidateForDelete
て原因を突き止めるなど、いくつかのチェックを実行しましたが、賢明にはなりませんでした。
編集:
フェッチされた結果コントローラーのデリゲート メソッドが原因ではないことは確かですが、完全を期すために の実装を追加しましたcontroller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
。
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
[self updateView];
switch(type) {
case NSFetchedResultsChangeInsert: {
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
case NSFetchedResultsChangeDelete: {
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
case NSFetchedResultsChangeUpdate: {
[self configureCell:(CCDStoreCell *)[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
}
case NSFetchedResultsChangeMove: {
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];
break;
}
default: {
break;
}
}
}