我已经阅读了关于这个错误的所有内容,但仍然无法确定它为什么会在我的应用程序中发生。
使用后台上下文保存多个 Core Data 对象时出现以下错误:
*** Terminating app due to uncaught exception "NSInternalInconsistencyException", reason: "Failed to process pending changes before save. The context is still dirty after 100 attempts. Typically this recursive dirtying is caused by a bad validation method, -willSave, or notification handler.
在下面的代码中,ArticleManager
'saddArticle
在主线程的循环中被调用。可能有 0-200 多篇文章要添加。此错误通常发生在文章计数 100-150 之间。
//ArticleManager.m
-(id)init
{
... //normal init stuff
dispatch_queue_t request_queue = dispatch_queue_create("com.app.articleRequest", NULL);
}
-(void) addArticle:(Article *)article withURLKey:(NSString *)url
{
//check if exists
if ([downloadedArticles objectForKey:url] == nil && article != nil)
{
//add locally
[downloadedArticles setObject:article forKey:url];
//save to core data
SaveArticle *saveArticle = [[SaveArticle alloc] init];
[saveArticle saveArticle:article withURL:url onQueue:request_queue];
}
}
//SaveArticle.m
@implementation SaveArticle
@synthesize managedObjectContext;
@synthesize backgroundContext;
-(id)init
{
if (![super init]) return nil;
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
managedObjectContext = [appDelegate managedObjectContext];
backgroundContext = [[NSManagedObjectContext alloc] init];
[backgroundContext setPersistentStoreCoordinator:[managedObjectContext persistentStoreCoordinator]];
return self;
}
-(void)saveArticle:(Article *)article withURL:(NSString *)url onQueue:(dispatch_queue_t)queue
{
//save persistently in the background
dispatch_async(queue, ^{
ArticleCache *articleCacheObjectModel = (ArticleCache *)[NSEntityDescription insertNewObjectForEntityForName:@"ArticleCache" inManagedObjectContext:backgroundContext];
if (article != nil)
{
[articleCacheObjectModel setArticleHTML:article.articleHTML];
[articleCacheObjectModel setUrl:url];
NSError *error;
//Save the background context and handle the save notification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(backgroundContextDidSave:)
name:NSManagedObjectContextDidSaveNotification
object:backgroundContext];
if(![backgroundContext save:&error]) //ERROR OCCURS HERE, after many saves
{
//This is a serious error saying the record
//could not be saved. Advise the user to
//try again or restart the application.
}
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSManagedObjectContextDidSaveNotification
object:backgroundContext];
}
});
}
/* Save notification handler for the background context */
- (void)backgroundContextDidSave:(NSNotification *)notification {
/* Make sure we're on the main thread when updating the main context */
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(backgroundContextDidSave:)
withObject:notification
waitUntilDone:NO];
return;
}
/* merge in the changes to the main context */
[self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
}
@end