更新:
在仪器上花了很多时间之后,当我切换视图时,我似乎偶然地节省了很多次核心数据。要解决这个问题,我将不得不重新安排大量如何在子视图中的数据输入字段中加载/保存数据。
但是,我确实发现当事件数量增加时导致的主要减速是每个Core Data保存,与Core Data相关的东西正在进行一堆重绘。
看起来这是原始的tableView正在执行[UITableView _updateWithItems:updateSupport]以及随之而来的所有UIKit动画。为了记录,这是一个股票UITableViewController与我的editViewController使用下面的prepareForSeque代码segue。
这是fetchedResultsControllers的作用吗?保持tableView的数据源更新,每次数据更改时tableView都会自行重绘,即使它不再可见?
(我还粘贴了这篇帖子底部的fetchedResultsController的其余代码,这样你就可以看到我如何更新表...再次,这是一个很好的锅炉板的东西,除了一个小修改我在表中添加新项目时做了。)
原始邮件:
在我使用Core Data的iOS应用程序中,我有一个UITableViewController,可正确查询Core Data并显示数据库中存在的“Event”对象(使用fetchedResultsController)。
当我从tableView转到编辑视图时,我会像这样传递所选的数据对象:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"EditEventSegue"]) {
// start a progress HUD
[SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeBlack];
// pass the selected Event object to EditViewController during segue
NSIndexPath *indexPath = [[self eventListTable] indexPathForSelectedRow];
Event *theEvent = [_fetchedResultsController objectAtIndexPath:indexPath];
EditViewController *editController = segue.destinationViewController;
editController.theEvent = theEvent;
// set EventListViewController as the delegate for the EditViewController
editController.delegate = self;
}
}
editController视图定义了一个属性来保存Event对象:
@property (strong, nonatomic) Event *theEvent;
通过在视图之间传递此对象,所有内容都可以在整个应用程序中运行(有多个视图可以从editController创建/销毁,并且它们也具有相同的theEvent属性定义)。
当我想保存数据时,我已经构建了一个协议,使用委托在视图链上发送“保存”消息(也许这不是最好的方法),原始的tableViewController进行保存(因为它拥有原始的托管对象上下文。)
所有这一切的主要问题是,我发现当我在数据库中有很多Event对象时,切换视图会慢下来!物体越多,它就越慢!我不确定为什么因为我只是传递指向原始tableView中选择的一个Event对象的指针。
是不是因为我在详细视图控制器中将theEvent定义为“强”?每个视图控制器是否只有弱引用?
此外,我已经阅读过关于传递托管对象上下文的内容,但即便如此,我也不确定如何传递对正确对象的引用,而不是我已经这样做了。各种编辑视图控制器(甚至您在上面的代码中看到的单个editController)如何知道正在编辑哪个对象?
任何想法或建议都会有所帮助。谢谢!
编辑:
这是来自包含起始tableView的控制器的代码:
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:_managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_managedObjectContext sectionNameKeyPath:nil cacheName:@"Root"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[self.eventListTable beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.eventListTable;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureCell:(EventCell *)[_eventListTable cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id )sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.eventListTable insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.eventListTable deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.eventListTable endUpdates];
// if a new event has just been added by the addEvent method then select it and segue to the Edit Details view
if (_justAddedNewEvent == YES) {
NSIndexPath *indexPath = [controller indexPathForObject:_newlyAddedEvent];
_justAddedNewEvent = NO;
// now open details view of newly added object
[self.eventListTable selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionBottom];
[self performSegueWithIdentifier:@"EditEventSegue" sender:self];
}
}