Я вижу ситуацию, когда NSFetchRequest возвращает разное количество объектов в зависимости от того, выполняется ли он напрямую через NSManagedObjectContext или как часть построения NSFetchedResultsController.
Образец кода:
- (void)setupResultsController {
NSError *error = nil;
NSManagedObjectContext *ctx = [[DataManager sharedInstance] mainObjectContext];
// Create a fetch request and execute it directly
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [Song entityInManagedObjectContext:ctx];
[fetchRequest setEntity:entity];
[fetchRequest setFetchBatchSize:20];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"section" ascending:YES];
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
NSArray *sortDescriptors = @[sortDescriptor, nameDescriptor];
[fetchRequest setSortDescriptors:sortDescriptors];
NSArray *debugResults = [ctx executeFetchRequest:fetchRequest error:&error];
NSLog(@"Count from context fetch: %lu", (unsigned long)debugResults.count);
// Use the request to populate a NSFetchedResultsController
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:ctx
sectionNameKeyPath:@"section"
cacheName:@"Detail"];
[aFetchedResultsController performFetch:&error];
NSLog(@"Count from results controller fetch: %lu", (unsigned long)[[aFetchedResultsController fetchedObjects] count]);
_songResultsController = aFetchedResultsController;
}
Выполнение вышеуказанного приводит к появлению сообщений журнала:
2020-01-10 11: 05: 07.892772-0500 asb7 [12985: 105052] Подсчет из выборки контекста: 10
2020-01-10 11: 05: 07.893259-0500 asb7 [12985: 105052] Счетчик из выборки контроллера результатов: 9
Разница между двумя выборками заключается в том, что в NSFetchedResultsController отсутствует последний добавленный объект. Крайняя странность в том, что после запуска приложения несколько, казалось бы, случайного числа раз, счетчики начинают согласовываться и выбирается новый объект.
Изменить:
Результаты станут согласованными, если я передам nil
в качестве имени кеша или если я удалю второй дескриптор сортировки. Очевидно, они вызывают нежелательные изменения поведения, но могут быть подсказками.
Кажется, что NSFetchedResultsController видит устаревший кеш как действительный. Изменение дескриптора сортировки делает кеш недействительным, однако обновление файла постоянного хранилища должно сделать его недействительным, но, по-видимому, не делает в этом случае.
После еще нескольких экспериментов у меня есть объяснение ... если не решение. Добавление новых объектов не меняет дату модификации моего файла .sqlite. Он обновляет .sqlite-shm и .sqlite-wal, но я предполагаю, что они не учитываются при оценке использования кеша. Использование touch
из сеанса терминала устраняет проблему при следующем запуске.
(Xcode 10.1, macOS 10.13.6, цель развертывания 10.3, симулятор iOS 12.1 и устройство 10.3.2)
Другое изменение:
Я загрузил заархивированный каталог проекта, который демонстрирует проблему, по адресу https://github.com/PhilKMills/CacheTest а>
Что я получаю: первый запуск, 3 записи для обоих выборок; второй прогон, 6 и 3. Я считаю вполне возможным, что это зависит от моей конкретной версии программного обеспечения, но я не в состоянии выполнить обновление в данный момент. Чужие результаты были бы наиболее интересными.
Примечание: без назначения делегата FRC проблема не возникает.
includesPendingChanges
на запрос fetchrequest. - person pbasdf   schedule 11.01.2020NSSQLitePragmasOption:@{@"journal_mode":@"DELETE"}
, и время модификации файла .sqlite обновляется. Спасибо еще раз! (Вы должны добавить сюда ответ.) - person Phillip Mills   schedule 11.01.2020sqlite3
из командной строки для проверки базы данных, записи, которые я ожидаю увидеть, сообщаются правильно, и, как я уже упоминал, использование контекста для выполнения выборки также дает правильный ответ. (Программа работала правильно в предыдущих версиях, хотя я не уверен, было ли это до WAL.) - person Phillip Mills   schedule 13.01.2020