NSFetchedResultsController 在 PerformFetch 上崩溃:使用缓存时
我利用 NSFetchedResultsController 来显示一堆对象,这些对象使用日期进行分段。在全新安装时,一切都运行良好,并且对象显示在表格视图中。然而,当应用程序重新启动时,我似乎崩溃了。我在初始化 NSFetchedResultsController 时指定了一个缓存,当我不指定时,它可以正常工作。
以下是我创建 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:'
我真的不知道为什么会这么说,因为我不相信我正在做任何特殊的事情会导致这种情况。唯一的潜在问题是节标题(日),我在创建新对象时构造如下:
// Set the new format
[formatter setDateFormat:@"dd MMMM"];
// Set the day of the event
[event setValue:[formatter stringFromDate:[event valueForKey:@"utc_start"]] forKey:@"day"];
就像我提到的,如果不涉及缓存,所有这些都可以正常工作。任何帮助表示赞赏!
I make use of NSFetchedResultsController to display a bunch of objects, which are sectioned using dates. On a fresh install, it all works perfectly and the objects are displayed in the table view. However, it seems that when the app is relaunched I get a crash. I specify a cache when initialising the NSFetchedResultsController, and when I don't it works perfectly.
Here is how I create my 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;
}
These are the messages I get when the app crashes:
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:'
I really have no clue as to why it's saying that, as I don't believe I'm doing anything special that would cause this. The only potential issue is the section header (day), which I construct like this when creating a new object:
// Set the new format
[formatter setDateFormat:@"dd MMMM"];
// Set the day of the event
[event setValue:[formatter stringFromDate:[event valueForKey:@"utc_start"]] forKey:@"day"];
Like I mentioned, all of this works fine if there is no cache involved. Any help appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
我通过 Ray Wenderlich 论坛发现
所以,在我的例子中发生的事情是这样的:
解决方案是确保在创建对象之前提取已完成(这会影响提取)。
或者,您可以删除缓存,但实际上性能较差。
请注意,调试器发出的警告
根本无法捕获这种情况,因为您更改的不是请求、谓词或排序描述符,但更准确地说,可以描述为在获取过程中改变了结果集。
我花了很长时间才找到这个小小的琐事。我希望你受益。
I found via the Ray Wenderlich forums that
So, what happened in my case was this:
The solution is to ensure that The fetch is complete before creating an object (which would affect the fetch).
Alternatively you could delete the cache, but that is less performant practically speaking.
Note that the admonition from the debugger that
simply does not capture this situation whatsoever, in that what you have changed was not the request, predicate, or sort descriptor, but rather more accurately could be described as having mutated the result set while the fetch was in progress.
It took me forever to track down this tiny piece of trivia. I hope you benefit.
将 @"Events" 替换为 nil。
replace @"Events" with nil.
当苹果发布新的 iOS 4.0 时,我的一个应用程序也遇到了类似的问题。
搜索:
并将参数cacheName的值设置为nil。它对我有用,希望对你也有用。让我知道。
I had a similar problem with one of my apps, when the Apple released the new iOS 4.0.
Search:
And set the value of the parameter cacheName to nil. It worked for me, hope it will for you. Let me know.
当我从 MacBook Pro 升级到 Snow Leopard 10.6.4 和最新的 SDK 时,我开始遇到同样的错误。
事实证明,我们中的许多人一直在使用不符合规则的代码,但我们并不知道这一点,因为 CoreData 并没有真正按照它自己的规则运行。
具体来说,当您获取内容时,它们会被缓存,而在 4.0 中,在早期 SDK 中清除缓存的情况下,该缓存不会自动清除。
对我来说,解决方案很简单。我只是使用了清除缓存的类方法。您可以指定一个单独的实体,但我指定了 nil,因此它只是在这段特定的启动代码中完成所有这些操作:
突然,我只是为了熟悉 CoreData 而开发的小应用程序又开始工作了。
I started getting the same error when I upgraded by MacBook Pro to Snow Leopard 10.6.4 and the latest SDK.
As it turns out, many of us had been using code that wasn't in conformance with the rules, but we didn't know it because CoreData wasn't really behaving in accordance with its own rules.
Specifically, when you fetch things, they get cached, and in 4.0, that cache isn't automatically purged in cases where it was purged in the earlier SDK.
For me, the solution was simple. I just employed the class method that purges the caches. You can specify an individual entity, but I specify nil so it just does them all in this particular piece of start-up code:
Suddenly, the little app I've worked on only to familiarize myself with CoreData is working again.
直接来自
NSFetchedResultsController
:Straight from the documentation for
NSFetchedResultsController
:我遇到了类似的问题。
当我检查调试器控制台时,它显示了缓存的对象和获取的对象是什么,以便我可以找出它们不一致的原因。
就我而言,这是由于不同的谓词造成的。
由于谓词中的值不是动态的,因此我可以为每个谓词指定不同的缓存名称。这将为我指定的每个“类型”创建一个缓存。
我想你必须评估你是否需要缓存。指定 nil 意味着每次调用都会进行一次提取。
我发现只有当获取请求有一些变化时才会发生错误。如果您正在创建新的 NSFetchRequest 或更改谓词或排序描述符,那么您应该删除缓存或使用不同的缓存。否则,请确保您有相同的 NSFetchRequest 或确保您的 NSFetchedResultsController 被保留,这应该可以解决您的问题。
I encountered a similar problem.
When I inspected the Debugger Console, it showed what the cached objects and the fetched objects were so that I could figure out why they are inconsistent.
In my case it was due to a different predicate.
Since the values in my predicate are not dynamic, I could specify a different cache name for each predicate. That will create a cache for each 'type' I specify.
I suppose you will have to assess your need to have the cache. To specify nil, means that a fetch is made in every call.
I figured out that the error occurs only when the fetch request have some changes. If you are creating a new NSFetchRequest OR changing the predicate OR sort descriptor, then you should delete the cache or use a different cache. Otherwise, ensure that you have the same NSFetchRequest or make sure that your NSFetchedResultsController is retained and that should solve your problem.
如果您正在使用模拟器,请尝试重置它 - 我猜您已经更改了实体映射,并且它被剩余的缓存弄糊涂了。如果没有,您可以尝试按照错误提示执行操作:
If you're using the simulator, try resetting it--I'd guess you've changed your entity map and it's getting confused by a leftover cache. If not, you could try doing what the error says:
Xcode 7(beta 4)仍然出现异常:
注意:这是使用未修改的 Xcode“模板”Master-Detail iOS 应用以及标准 Xcode CoreData“boiler-plate”< /em> 使用 Xcode 7 创建并使用最新 (iOS 9) 部署目标的代码。
当我在模拟器中重新启动我的应用程序时,我首先注意到了这一点。我已经通过 Xcode 多次启动和停止该应用程序,然后就发生了;这种事一直在发生。我决定做一些实验,结果是:
使用以下方法中的其中一个仍然可以按如下方式修复:
application didFinishLaunchingWithOptions
方法中,添加以下内容SwiftNSFetchedResultsController.deleteCacheWithName(nil)
或 Objective-C[NSFetchedResultsController deleteCacheWithName:nil];
代码。这会清除损坏的缓存。我还相信这是通过 Xcode 运行并在应用程序能够清理之前停止应用程序的产物。我在实际设备中没有看到这一点。
The exception still occurs with Xcode 7 (beta 4):
NOTE: This is with an unmodified Xcode "Template" Master-Detail iOS app with standard Xcode CoreData "boiler-plate" code created with Xcode 7 and using the latest (iOS 9) deployment target.
I noticed it first when I restarted my app in the simulator. I had been starting and stopping the app several times via Xcode and then it happened; and it kept happening. I decided to do some experiments, and the results:
The issue can still be fixed as follows, using one or the other of the following methods:
application didFinishLaunchingWithOptions
method, add the following SwiftNSFetchedResultsController.deleteCacheWithName(nil)
or Objective-C[NSFetchedResultsController deleteCacheWithName:nil];
code. This clears out the corrupted cache.I also believe that this is an artifact of running via Xcode and stopping the app prior to it being able to clean up. I've not seen this in the actual device.
您是使用主页按钮还是通过在 Xcode 中终止应用程序来退出模拟器?也许应用程序没有时间完成对缓存的写入。尝试使用主页按钮退出应用程序。
Are you quitting the Simulator using the home button or by terminating the app in Xcode? Maybe the app isn't getting time to finish writing to the cache. Try using the home button to quit the app.
有多少个类实现相同的 - (NSFetchedResultsController *)results 方法,您是否为每个类使用不同的缓存?我遇到了同样的问题,我想我可以通过在某些类之前使用不同的缓存名称来修复它,因为我有不同的 NSPredicates。
How many classes implement the same - (NSFetchedResultsController *)results method, do you use a different cache for each one? I was having the same issue and I think I fix it by using a different cache name fore some clases since I have different NSPredicates.
我也遇到了同样的问题。
为了解决这个问题,我将
[NSFetchedResultsController deleteCacheWithName:@"cacheName"];
放在 resultsController 的 init 之前。对我有用,因为他只第一次去那里。I was having the same problem.
To fix, I put the
[NSFetchedResultsController deleteCacheWithName:@"cacheName"];
before the init of resultsController. Works for me as he only goes there on the first time.对于现在遇到同样问题的人来说,问题是 Core Data 不清理缓存,所以第一次工作正常,但之后就不行了。然后只需在初始化 NSFetchRequest 之后放置此行
For those who run into the same problem nowadays, the problem is that somehow Core Data doesn't clean the cache so work fine at first time but doesn't after that. Then just put this line right after init the NSFetchRequest