我正在尝试确定一个使我的应用程序崩溃多年的错误。然而,我花了很长时间来缩小原因,我想我(几乎)有它。如果应用程序进入后台,它会运行一个后台任务来清理数据库,并在两个月后删除文章订单。
如果碰巧有符合条件的文章,并且 UITableView 打开并显示此特定列表,则应用程序崩溃,因为查询NSFetchedResultsController
结果经常出现以下错误:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no section at index 26'
或者有时:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
调用时:(_objects 是 NSFetchedResultsController)
[_objects objectAtIndexPath:[NSIndexPath indexPathForRow:currentRow inSection:indexPath.section]]
由触发
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
所以我想知道这是否是因为NSFetchedResultsController
当应用程序退出活动时(在主线程上)对后台任务/线程不可用(正确)。这是解释吗?如果是这样,我如何防止这种正确的形式发生?
我可以阻止合并更改,但是当应用程序返回前台时ManagedObjectContect
,如何确保它已更新,并且更改反映在 中?UITableView
只是一个理论。我知道崩溃发生在后台进程中,但还没有更多。当应用程序处于活动状态时,更新、删除、删除工作正常。
更新代码更正:后台进程的调用
- (void)performMaintenance{
UIApplication *application = [UIApplication sharedApplication]; //Get the shared application instance
__block UIBackgroundTaskIdentifier background_task; //Create a task object
background_task = [application beginBackgroundTaskWithExpirationHandler: ^ {
[application endBackgroundTask: background_task]; //Tell the system that we are done with the tasks
background_task = UIBackgroundTaskInvalid; //Set the task to be invalid
//System will be shutting down the app at any point in time now
}];
//Background tasks require you to use asyncrous tasks
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//Perform your tasks that your application requires
NSLog(@"\n\nRunning maintenance in the background!\n\n");
// Perform work that should be allowed to continue in background
[self doMaintenance];
[application endBackgroundTask: background_task]; //End the task so the system knows that you are done with what you need to perform
background_task = UIBackgroundTaskInvalid; //Invalidate the background_task
});
}
#pragma mark Actions
- (void)doMaintenance{
DODataManager *data = [[DODataManager alloc] init];
NSDateComponents *components = [[NSDateComponents alloc] init];
components.month = -2;
NSDate *twoMonthsBeforeNow = [[NSCalendar currentCalendar] dateByAddingComponents:components toDate:[NSDate date] options:0];
NSFetchedResultsController* controller = [data getArticlesBeforeDate:twoMonthsBeforeNow];
NSLog(@"Cleaning up database, removing %i items", controller.fetchedObjects.count);
for(DOArticle* article in controller.fetchedObjects){
[controller.managedObjectContext deleteObject:article];
}
// Update the unread count and unread count (if dataconenction available)
[data updateBadge];
[data commitChanges];
data=nil;
NSMutableDictionary* dict = [NSMutableDictionary dictionaryWithObject:@"1.0" forKey:@"progress"];
[[NSNotificationCenter defaultCenter] postNotificationName:kDialogUpdate object:dict];
NSLog(@"Finished maintenace!");
}
清理现在在一个单独的线程中正确进行,并且通知被发送到主线程,但仍然是同样的问题。
2014-01-27 22:16:34.541 iDomsPortalDev[1963:5107] Cleaning up database, removing 2 items
2014-01-27 22:16:36.024 iDomsPortalDev[1963:5107] Start for 3 items on object Setting!
2014-01-27 22:16:36.026 iDomsPortalDev[1963:5107] Removing 0 stat items
2014-01-27 22:16:36.029 iDomsPortalDev[1963:70b] Merging changes!
2014-01-27 22:16:36.030 iDomsPortalDev[1963:70b] Delete