NSFetchedResultsController crashing on performFetch: when using a cache

后端 未结 12 1996
迷失自我
迷失自我 2020-12-23 14:05

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 displ

相关标签:
12条回答
  • 2020-12-23 14:08

    Straight from the documentation for NSFetchedResultsController:

    Modifying the Fetch Request

    You cannot simply change the fetch request to modify the results. If you want to change the fetch request, you must:

    1. If you are using a cache, delete it (using deleteCacheWithName:). Typically you should not use a cache if you are changing the fetch request.

    2. Change the fetch request.

    3. Invoke performFetch:.

    0 讨论(0)
  • 2020-12-23 14:10

    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

    [NSFetchedResultsController deleteCacheWithName:@"Name"];
    
    0 讨论(0)
  • 2020-12-23 14:13

    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.

    0 讨论(0)
  • 2020-12-23 14:13

    I found via the Ray Wenderlich forums that

    Note that it only crashes when the fetch request is not created yet when you add something new to the datastore, i.e. when the Locations view isn't loaded yet. If the view is loaded already, then it works fine. Odd, eh?

    So, what happened in my case was this:

    1. The normal launch process entails constructing an NSFetchedResultsController.
    2. Because there are thousands of objects being fetched, a fresh fetch takes considerable time. To mitigate this, the fetch a) uses a cache, and b) happens in the background, allowing other activities to continue
    3. Normally, though the UI is responsive and the user can do stuff, the fetch is complete long before the user might express a desire to create a new object.
    4. However, sometimes the app will be launched in the background - say, from a WatchKit event, or a background fetch, etc) - and part of the launch will entail creating a new object in the datastore immediately.
    5. If the new object was created before the fetch was complete, the app would crash.

    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

    You have illegally mutated the NSFetchedResultsController's fetch request, its predicate, or its sort descriptor without either disabling caching or using +deleteCacheWithName:

    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.

    0 讨论(0)
  • 2020-12-23 14:15

    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.

    0 讨论(0)
  • 2020-12-23 14:21

    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.

    0 讨论(0)
提交回复
热议问题