gpt4 book ai didi

ios - 在后台使用 NSFetchedResultsController 自动 UITableView

转载 作者:行者123 更新时间:2023-11-29 03:18:45 25 4
gpt4 key购买 nike

我正试图确定一个让我的应用程序崩溃多年的错误。然而,我花了很长时间才缩小原因的范围,我想我(几乎)明白了。如果应用程序进入后台,它会运行一个后台任务来清理数据库,并在两个月后删除文章订单。

如果碰巧有符合条件的文章,并且 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 合并更改,但是我如何确保它已更新,并且当 App 返回时更改反射(reflect)在 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

最佳答案

您正在从异步 GCD block 调用 doMaintainance,并且您正在访问托管对象上下文。

托管对象上下文不是线程安全的

关于ios - 在后台使用 NSFetchedResultsController 自动 UITableView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21376691/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com