刷新NSFetchedResultsController数据?

我可以在我的应用程序中创建新的托管对象,在单独的视图中我有一个表格视图,显示我拥有的所有对象。

当我创建一个新的托管对象(在一个完全独立的视图中)时,我发出一个通知,试图让我的表视图重新加载包含我刚制作的新对象的新数据。

我不是在编辑表格视图。

只有一个托管上下文。

我无法理解我做错了什么。 如果我关闭应用程序并重新启动我的新对象是在表视图中。 当我收到通知时,我试图调用reloadData一个新的对象,我也尝试再次执行获取,但我最终得到的只是一个空表视图。

在代码方面,我的ListViewController:

@interface MyNotesViewController : UIViewController { NSManagedObjectContext * __managedObjectContext; UITableView * _notesTableView; MyNotesTableViewDelegate_DataSource * _tableDelegate_DataSource; } 

我的viewDidLoad看起来像这样:

 - (void)viewDidLoad { [super viewDidLoad]; _tableDelegate_DataSource = [[MyNotesTableViewDelegate_DataSource alloc] init]; _tableDelegate_DataSource.managedObjectContext = __managedObjectContext; [_notesTableView setDataSource:_tableDelegate_DataSource]; NSError * _coreDataError; BOOL success = [[_tableDelegate_DataSource fetchedResultsController] performFetch:&_coreDataError]; if(success){ [_notesTableView reloadData]; } } 

在我的委托/数据源对象中,我有:

 @interface MyCommutesTableViewDelegate_DataSource : NSObject  { NSManagedObjectContext * __managedObjectContext; NSFetchedResultsController * __fetchedResultsController; } @property (nonatomic, retain) NSManagedObjectContext *managedObjectContext; @end 

实施摘录:

 -(NSFetchedResultsController*)fetchedResultsController{ if(!__fetchedResultsController){ NSFetchRequest * request = [[NSFetchRequest alloc] init]; [request setEntity:[NSEntityDescription entityForName:@"Note" inManagedObjectContext:__managedObjectContext]]; [request setFetchBatchSize:10]; NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"noteDate" ascending:NO]; [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]]; [sortDescriptor release]; __fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request managedObjectContext:__managedObjectContext sectionNameKeyPath:nil cacheName:nil]; __fetchedResultsController.delegate = self; [request release]; } return __fetchedResultsController; } 

我在这里有stander UITableView数据源方法:

 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ id  sectionInfo = [[__fetchedResultsController sections] objectAtIndex:section]; return [sectionInfo numberOfObjects]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"NotesTableViewCell"; NotesTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { NSArray * topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"NotesTableViewCell" owner:nil options:nil]; for(id currentObject in topLevelObjects){ if([currentObject isKindOfClass:[UITableViewCell class]]){ cell = (NotesTableViewCell*) currentObject; break; } } } // Configure the cell. Note * _note = [__fetchedResultsController objectAtIndexPath:indexPath]; [...] return cell; } 

UPDATE

我只是简单地请求所有对象,因为我必须快速修复我的问题,然后我意识到,在我保存上下文之后,我之前在应用程序启动时使用的获取请求,现在没有返回数据,没有错误,但它只是没有回报。

所以我想我如何实现NSFetchResultsController没有问题。 但是在保存新对象后,请求怎么能开始不返回结果呢?

注意如果我重新启动,我仍然可以获得所有对象,包括新添加的对象。

标准要求:

 -(NSArray*)getNotes{ NSFetchRequest * request = [[NSFetchRequest alloc] init]; NSEntityDescription * entity = [NSEntityDescription entityForName:@"Note" inManagedObjectContext:[self managedObjectContext]]; [request setEntity:entity]; NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"noteDate" ascending:NO]; [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]]; [sortDescriptor release]; NSError * coreDataError; NSArray * fetchedObjects = [[self managedObjectContext] executeFetchRequest:request error:&coreDataError]; [request release]; if(fetchedObjects != nil){ return fetchedObjects; } else { NSLog(@"ERR: %@", coreDataError); return nil; } } 

我正在等待通知告诉我一个新对象已添加到Core Data,然后我调用上面的方法,然后在我的tableview上调用reloadData …

您将UITableViewController设置为NSFetchedResultsControllerDelegate 。 那很好。 现在尝试在TableViewController中实现controllerDidChangeContent:方法,如下所示:

 - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [self.tableView reloadData]; } 

您的NSFetchedResultsController将侦听Core Data中的已删除或新对象,并通知其委托(您的TableViewController)更改。 检查Xcode中的Core Data模板项目,通过UITableView中的添加和删除动画更好地实现这一点。

一定要添加didChangeObject方法:

 - (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id) anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { 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:[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; } } - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { NSManagedObject *note = [self.fetchedResultsController objectAtIndexPath:indexPath]; cell.textLabel.text = [note valueForKey:@"title"]; } 

在此之后,新的托管对象显示在表视图中。

万一有人有同样的问题,就像我刚才那样。 我用绿色勾选了上面的解决方案,但它对我不起作用。 我已经关注了Apple的代码 ,一切都很顺利。

简单地说,只需实现三个“Fetchcontroller”委托函数

  func controllerWillChangeContent(controller: NSFetchedResultsController) { self.tableView.beginUpdates() } func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) { switch type { case .Insert: self.tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade) case .Delete: self.tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) case .Update: print("") self.configureCell(self.tableView.cellForRowAtIndexPath(indexPath!)!, indexPath: indexPath!) case .Move: self.tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) self.tableView.insertRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade) } } func controllerDidChangeContent(controller: NSFetchedResultsController) { self.tableView.endUpdates() }