执行caching时,NSFetchedResultsController崩溃:使用caching时

我使用NSFetchedResultsController来显示一堆对象,这些对象使用date进行分区。 在全新的安装中,这一切都完美地工作,对象显示在表视图中。 但是,似乎应用程序重新启动时,我得到一个崩溃。 我在初始化NSFetchedResultsController的时候指定了一个caching,当我没有完美的工作的时候。

这里是我如何创build我的NSFetchedResultsController:

- (NSFetchedResultsController *)results { // If we are not nil, stop here if (results != nil) return results; // Create the fetch request, entity and sort descriptors NSFetchRequest *fetch = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext]; NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"utc_start" ascending:YES]; NSArray *descriptors = [[NSArray alloc] initWithObjects:descriptor, nil]; // Set properties on the fetch [fetch setEntity:entity]; [fetch setSortDescriptors:descriptors]; // Create a fresh fetched results controller NSFetchedResultsController *fetched = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"day" cacheName:@"Events"]; fetched.delegate = self; self.results = fetched; // Release objects and return our controller [fetched release]; [fetch release]; [descriptor release]; [descriptors release]; return results; } 

这些是我在应用程序崩溃时得到的消息:

 FATAL ERROR: The persistent cache of section information does not match the current configuration. You have illegally mutated the NSFetchedResultsController's fetch request, its predicate, or its sort descriptor without either disabling caching or using +deleteCacheWithName: *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'FATAL ERROR: The persistent cache of section information does not match the current configuration. You have illegally mutated the NSFetchedResultsController's fetch request, its predicate, or its sort descriptor without either disabling caching or using +deleteCacheWithName:' 

我真的不知道为什么这么说,因为我不相信我会做出任何特殊的事情来造成这种情况。 唯一的潜在问题是节头(date),我创build一个新的对象时,我这样构造:

 // Set the new format [formatter setDateFormat:@"dd MMMM"]; // Set the day of the event [event setValue:[formatter stringFromDate:[event valueForKey:@"utc_start"]] forKey:@"day"]; 

就像我提到的,如果没有涉及caching的话,所有这些都可以正常工作。 任何帮助感激!

当苹果发布新的iOS 4.0时,我遇到了类似的问题。 search:

 fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:[self managedObjectContext] sectionNameKeyPath:nil cacheName:nil]; 

并将参数cacheName的值设置为nil。 它为我工作,希望它会为你。 让我知道。

当我将MacBook Pro升级到Snow Leopard 10.6.4和最新的SDK时,我开始出现同样的错误。

事实certificate,我们中的许多人一直在使用不符合规则的代码,但是我们并不知道它,因为CoreData并没有真正按照自己的规则行事。

具体来说,当您获取内容时,它们会被caching,而在4.0版本中,如果在早期的SDK中清除caching,则不会自动清除caching。

对我来说,解决办法很简单。 我只是采用清除caching的类方法。 你可以指定一个单独的实体,但是我指定了nil,所以它只是在这个特定的启动代码中完成它们:

 [NSFetchedResultsController deleteCacheWithName:nil]; 

突然之间,我所做的只是为了让自己熟悉CoreData的小应用程序再次工作。

直接从NSFetchedResultsController的文档:

修改提取请求

您不能简单地更改获取请求来修改结果。 如果您想更改获取请求,您必须:

  1. 如果您正在使用caching,请将其删除(使用deleteCacheWithName: 。 通常情况下,如果您更改提取请求,则不应使用caching。

  2. 更改提取请求。

  3. 调用performFetch:

我遇到了类似的问题。 当我检查debugging器控制台时,它显示了caching的对象和提取的对象,以便我可以找出为什么它们不一致。 在我的情况下,这是由于一个不同的谓词。

由于我的谓词中的值不是dynamic的,我可以为每个谓词指定一个不同的caching名称。 这将为我指定的每个“types”创build一个caching。

我想你将不得不评估你需要有caching。 要指定nil,表示在每个调用中都进行一次提取。

我发现只有当获取请求有一些变化时才会出现错误。 如果您正在创build新的NSFetchRequest或更改谓词或sorting描述符,则应该删除caching或使用不同的caching。 否则,请确保您具有相同的NSFetchRequest或确保您的NSFetchedResultsController被保留,并且应该可以解决您的问题。

如果你正在使用模拟器,请尝试重置它 – 我猜你已经改变了你的实体图,并且被剩下的caching弄糊涂了。 如果没有,你可以尝试做错误说:

 - (void)applicationWillTerminate:(UIApplication *)application { [NSFetchedResultsController deleteCacheNamed:@"Events"]; //etc } 

Xcode 7(testing版4)仍然会出现exception情况:

您已经非法修改了NSFetchedResultsController的获取请求,谓词或者其sorting描述符,而没有禁用caching或者使用+ deleteCacheWithName:

注意:这是与一个未修改的Xcode“模板”主详细iOS应用程序与标准的Xcode CoreData “锅炉”代码创build的Xcode 7和使用最新的(iOS 9)部署目标。

我首先注意到,当我在模拟器中重新启动我的应用程序。 我已经通过Xcode几次启动和停止应用程序,然后发生了; 并一直在发生。 我决定做一些实验,结果是:

  • 每当我在模拟器中停止应用程序,我都会在随后的启动中得到例外。
  • 每当我使用模拟器的主页button停止应用程序时,我都能够成功启动它。

这个问题仍然可以通过以下方法之一修复

  • 在AppDelegate的application didFinishLaunchingWithOptions方法中,添加下面的Swift NSFetchedResultsController.deleteCacheWithName(nil)或Objective-C [NSFetchedResultsController deleteCacheWithName:nil]; 码。 这清除了损坏的caching。
  • 在模拟器中,从模拟器菜单中select重置内容和设置 。 这解决了这个问题,但是你失去了testing数据

我也相信这是一个通过Xcode运行的工件,并在能够清理之前停止应用程序。 我没有在实际的设备中看到这个。

你正在使用主页button或终止在Xcode的应用程序退出模拟器? 也许应用程序没有时间完成写入caching。 尝试使用主页button退出应用程序。

有多less类实现相同的(NSFetchedResultsController *)结果方法,你使用每个不同的caching? 我遇到了同样的问题,我想我通过使用不同的caching名称来解决它,因为我有不同的NSPredicates。

我遇到了同样的问题。
为了解决,我把[NSFetchedResultsController deleteCacheWithName:@"cacheName"]; 在resultsController的init之前。 因为他只是第一次去那里工作。

对于那些现在遇到同样问题的人来说,问题是核心数据不会清理caching,因此在第一时间工作正常,但不会在那之后。 然后,只需在NSFetchRequest初始化之后放置此行

 [NSFetchedResultsController deleteCacheWithName:@"Name"]; 

我通过Ray Wenderlich 论坛发现了这一点

请注意,只有在向数据存储中添加新内容 (即“位置”视图尚未加载)时, 才会创build提取请求时才会崩溃。 如果视图已经加载,那么它工作正常。 奇怪的,呃?

那么,我的情况是这样的:

  1. 正常的启动过程需要构build一个NSFetchedResultsController。
  2. 因为有成千上万的对象被抓取,所以重新获取需要相当长的时间。 为了缓解这个问题,提取a)使用一个caching,并且b)发生在后台,允许其他活动继续
  3. 通常,尽pipeUI是响应式的并且用户可以做东西,但是在用户可能expression创build新对象的愿望之前,获取是完整的。
  4. 然而,有时应用程序将在后台启动 – 例如,从WatchKit事件或后台提取等) – 启动的一部分将需要立即在数据存储中创build一个新的对象。
  5. 如果新对象是在提取完成之前创build的,则应用程序将崩溃。

解决scheme是确保在创build对象之前完成提取 (这会影响提取)。

或者,您可以删除caching,但实际上性能较差。

请注意,来自debugging器的警告

您已经非法修改了NSFetchedResultsController的获取请求,谓词或者其sorting描述符,而没有禁用caching或者使用+ deleteCacheWithName:

根本不能捕获这种情况,因为你已经改变的不是请求,谓词或者sorting描述符,而是更确切地说可以被描述为在提取正在进行时突变了结果集

我永远花了我的时间来追查这个小小的琐事。 我希望你能受益

 NSFetchedResultsController *fetched = [[NSFetchedResultsController alloc] initWithFetchRequest:fetch managedObjectContext:self.managedObjectContext sectionNameKeyPath:@"day" cacheName:@"Events"]; 

用nilreplace@“Events”。