iOS:保存托pipe对象上下文需要一段时间

奇怪的问题,奇怪的只有自从昨天。 我有一个获取结果控制器,您可以在其中重新sorting行没有任何问题。 应用程序重新启动后,一切正常,快速。 但是,如果您从此选项卡栏更改为另一个选项卡栏并编辑一些随机文本字段(甚至没有链接到核心数据,并且不会触发任何保存),重新sorting非常缓慢。 而且我只能把它缩小到保存的范围内。 但是现在我不知道该往哪里看。 有什么build议? 这是我的重新sortingfunction:

- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath; { if (self.activeField && [self.activeField isFirstResponder]){ [self.activeField resignFirstResponder]; } self.suspendAutomaticTrackingOfChangesInManagedObjectContext = YES; //Makes only a mutable copy of the array, but NOT the objects (references) within NSMutableArray *fetchedResults = [[self.fetchedResultsController fetchedObjects] mutableCopy]; // Grab the item we're moving NSManagedObject *resultToMove = [self.fetchedResultsController objectAtIndexPath:sourceIndexPath]; // Remove the object we're moving from the array. [fetchedResults removeObject:resultToMove]; // Now re-insert it at the destination. [fetchedResults insertObject:resultToMove atIndex:[destinationIndexPath row]]; // All of the objects are now in their correct order. Update each // object's displayOrder field by iterating through the array. int i = 1; for (MainCategory *fetchedResult in fetchedResults) { fetchedResult.position = [NSNumber numberWithInt:i++]; } // Save TICK; [((AppDelegate *)[[UIApplication sharedApplication] delegate]) saveContext]; TOCK; self.suspendAutomaticTrackingOfChangesInManagedObjectContext = NO; } 

昨天我只插入了这两个方法(这不是问题,因为在注释它们之后,它们不会触发,同样的问题依然存在):

 -(void) registerForKeyboardNotificationsWithTabBarHeight:(CGFloat)tabbarHeight andHeaderHeight:(CGFloat)headerHeight andFooterHeight:(CGFloat)footerHeight andBottomSpacingToTextFields:(CGFloat)spacingToTextFields { self.tabbarHeight = tabbarHeight; self.footerHeight = footerHeight; self.headerHeight = headerHeight; self.spacingToTextFields = spacingToTextFields; // Register notification when the keyboard will be show [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; // Register notification when the keyboard will be hide [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; } 

FetchedResultsController:

 - (void)setupFetchedResultsController { self.managedObjectContext = ((AppDelegate *)[[UIApplication sharedApplication] delegate]).managedObjectContext; NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"MainCategory"]; request.sortDescriptors = [NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"position" ascending:YES]]; self.fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"MainCategoryCache"]; } 

而且这个视图也会很无害

 - (void)viewWillAppear:(BOOL)animated { //Initialize database [super viewWillAppear:animated]; [self displayBudget]; /* This is only necessary since the sum of all categories is calculated and the FetchedResultsController doesn't get this since it's only monitoring a MainCategory and the changes occured in the Subcategories */ [self.tableView reloadData]; } 

我感谢任何线索可能是什么问题:-(

在这种情况下我不会推荐multithreading。 问题是你的保存是在错误的时间完成的。 将它们移到后台队列不会解决问题。 你需要改变你的保存行为。

写入磁盘是昂贵的。 周围没有捷径。 即使你把保存到另一个上下文(有一个苹果的例子),他们仍然需要时间,并可能会阻止你的用户界面(保存期间你不能做一个新的提取)。 你需要改变你的保存行为。

每当用户移动一行时,都不需要保存。 这是浪费。 你想排队你的保存,这样你每做更多的保存。 另外,当用户期望有一个延迟时,你应该保存。 当你推动或popup一个视图可能是一个保存的好时机。 当你的应用程序进入后台是一个伟大的时间来保存。

当用户想要stream畅的UI响应时保存是不好的,并导致不良的用户体验。 寻找用户需要花费时间的机会。 发布到服务器的东西? 保存在同一时间。

您的NSFetchedResultsController等将读取您的主NSManagedObjectContext未保存的数据,就像它将保存数据一样。 通过经常保存,你不会在UI上获得任何东西。

更新1

性能问题的第一步是在Instruments中运行你的应用程序。

测量速度,然后看看你花了多less时间。 时间分析器是你的朋友。

是的,它会减慢绘制你的用户界面,因为你不应该在主队列中使用保存和创build对象; 阅读这个https://developer.apple.com/library/ios/documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html

你应该有另一个后台线程,你应该插入删除的东西那里,然后你必须通过NSObjectID_s newManagedObject_s然后得到它在主线程:

NSManagedObjectContext * mainThreadContext;

NSManagedObject * object = [mainThreadContext objectWithId:objectID];