UITableView with NSFetchedResultsController Does Not Load the Second Time

核能气质少年 提交于 2019-11-30 13:51:50

Contrary to what I assumed in above comment, the same effect can happen if a sectionNameKeyPath is specified to create table view sections (I could reproduce this with a test program).

When the app is started the first time, the following happens:

  1. A persistent store file "appname.sqlite" is created.
  2. A fetched results controller for the table view is created with the cacheName parameter set, so that a section cache file is created. At this point, all sections are empty.
  3. A background MOC is created that reads some JSON data from a resource file and add objects to the context.
  4. The background MOC is saved.

(Btw. the cache file is

   Library/Caches/<bundle-id>/.CoreDataCaches/SectionInfoCaches/<tablename>/sectionInfo

in the application bundle.)

When the app is started the second time, the fetched results controller checks whether the section info cache is still valid or has to be recreated. According to the documentation it compares the modification times of the persistent store file and the section cache file.

Now the interesting part: If (in the first run) the creation of the store file (step 1) and saving the updated context (step 4) happen in the same second, then the modification date of the store file is not changed in step 4!!

Therefore the section cache file is still seen as valid and not recreated. Since all sections were empty (in step 2), the FRC uses this cached information and displays only empty sections.

The background MOC is started again and saves the context. Now the store file has a new modification date, therefore the sections and rows are displayed correctly in the third run of the app.

To confirm my "theory", I did a manual "touch" of the store file between first and second run to enforce a changed modification date. All sections and rows were then displayed correctly.

(I tested this only in the iPhone Simulator. I don't know if the HFS+ file system generally has a 1 second resolution of the modification date, or if SQLite does something special here. I will try to investigate that later.)

Conclusion: If the creation of the store file and saving modified data happen in the same second, a section info cache file might not be regenerated if necessary.

I ran into the same problem. When I loaded the data, the first load was fine. When I restarted my app, the data disappeared from the table. These were my counts:

self.fetchedResultsController.fetchedObjects: 8
[self.fetchedResultsController.sections count]: 1
[self.fetchedResultsController.sections[0] numberOfObjects]: 0

I have the ability to change the sort in the UI and after changing the sort and then changing it back again, the issue disappeared, which definitely pointed to a caching issue.

Calling

[NSFetchedResultsController deleteCacheWithName:nil];

will delete all caches.

I also ended up choosing not to cache for now. I don't think I will store tens of thousands of records in my database for these tables, so I'm not sure if caching will improve anything. Setting cacheName to nil will prevent any caching for NSFetchedResultsController.

self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                                    managedObjectContext:self.context
                                                                      sectionNameKeyPath:sectionIdentifier
                                                                               cacheName:nil];
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!