NSFetchedResultsController не отображает изменения из фонового потока

Мое приложение использует NSFetchedResultsController, привязанный к хранилищу основных данных, и до сих пор он работал хорошо, но теперь я пытаюсь сделать асинхронный код обновления, и у меня возникают проблемы. Я создал подкласс класса NSOperation для выполнения моих обновлений и успешно добавляю этот новый объект в NSOperationQueue. Код обновления выполняется, как я ожидаю, и я проверил это через журналы отладки и проверил хранилище SQLite после его запуска.

Проблема в том, что после завершения моей фоновой операции новые (или обновленные) элементы не отображаются в моем UITableView. Основываясь на моем ограниченном понимании, я считаю, что мне нужно уведомить основной файл managedObjectContext о том, что произошли изменения, чтобы они могли быть объединены. Мое уведомление срабатывает, гайка не содержит новых элементов в представлении таблицы. Если я остановил приложение и перезапустил его, объекты появятся в представлении таблицы, что приведет меня к тому, что они будут успешно вставлены в хранилище основных данных, но не будут объединены в управляемый элемент управления, который будет использоваться в основном потоке.

Я включил образец методов инициализации, основного и уведомления моей операции. Я пропустил что-то важное или, возможно, об этом не так? Любая помощь будет принята с благодарностью.

- (id)initWithDelegate:(AppDelegate *)theDelegate { if (!(self = [super init])) return nil; delegate = theDelegate; return self; } - (void)main { [self setUpdateContext:[self managedObjectContext]]; NSManagedObjectContext *mainMOC = [self newContextToMainStore]; NSNotificationCenter *center = [NSNotificationCenter defaultCenter]; [center addObserver:self selector:@selector(contextDidSave:) name:NSManagedObjectContextDidSaveNotification object:updateContext]; [self setMainContext:mainMOC]; // Create/update objects with mainContext. NSError *error = nil; if (![[self mainContext] save:&error]) { DLog(@"Error saving event to CoreData store"); } DLog(@"Core Data context saved"); } - (void)contextDidSave:(NSNotification*)notification { DLog(@"Notification fired."); SEL selector = @selector(mergeChangesFromContextDidSaveNotification:); [[delegate managedObjectContext] performSelectorOnMainThread:selector withObject:notification waitUntilDone:YES]; } 

Во время отладки я исследовал объект notification , который отправляется в contextDidSave: и, кажется, он содержит все элементы, которые были добавлены (выдержка ниже). Это продолжает заставлять меня думать, что вставки / обновления происходят правильно, но каким-то образом слияние не запускается.

 NSConcreteNotification 0x6b7b0b0 {name = NSManagingContextDidSaveChangesNotification; object = <NSManagedObjectContext: 0x5e8ab30>; userInfo = { inserted = "{(\n <GCTeam: 0x6b77290> (entity: GCTeam; id: 0xdc5ea10 <x-coredata://F4091BAE-4B47-4F3A-A008-B6A35D7AB196/GCTeam/p1> ; data: {\n changed = 

4 Solutions collect form web for “NSFetchedResultsController не отображает изменения из фонового потока”

Метод, который получает ваше уведомление, должен действительно уведомлять ваш контекст, вы можете попробовать что-то вроде этого, что я и делаю в своем приложении:

  - (void)updateTable:(NSNotification *)saveNotification { if (fetchedResultsController == nil) { NSError *error; if (![[self fetchedResultsController] performFetch:&error]) { //Update to handle the error appropriately. NSLog(@"Unresolved error %@, %@", error, [error userInfo]); exit(-1); // Fail } } else { NSManagedObjectContext *context = [fetchedResultsController managedObjectContext]; // Merging changes causes the fetched results controller to update its results [context mergeChangesFromContextDidSaveNotification:saveNotification]; // Reload your table view data [self.tableView reloadData]; } } 

Надеюсь, это поможет.

В зависимости от специфики того, что вы делаете, вы можете ошибаться в этом.

В большинстве случаев вы можете просто назначить делегата, используя NSFetchedResultsControllerDelegate . Вы предоставляете реализацию для одного из методов, указанных в «responseingToChanges» в зависимости от ваших потребностей, а затем отправляете tableView сообщение reloadData.

Ответ оказался не связанным с опубликованным кодом, который закончился тем, что я ожидал. По причинам, по которым я все еще не совсем уверен, это как-то связано с первым запуском приложения. Когда я попытался запустить мою операцию обновления при запуске после создания хранилища основных данных, он работал, как ожидалось. Я решил проблему, предварительно загрузив версию базы данных sqlite в приложение, чтобы при первом запуске не нужно создавать пустые хранилища. Хотел бы я понять, почему это решило проблему, но я планировал сделать это в любом случае. Я оставляю это здесь в надежде, что кто-то другой найдет его полезным и не потеряет столько времени, сколько я сделал по этому поводу.

У меня возникла аналогичная проблема в симуляторе. Я начинал процесс обновления при переходе от корневой таблицы к выбранной папке. Процесс обновления будет обновлять CoreData с веб-сервера, сохранять, а затем объединять, но данные не отображаются. Если бы я несколько раз смотрел взад-вперед, это проявлялось в конце концов, и как только это работало, как часы (но я никогда не мог повторить этот идеальный пробег). Это дало мне представление о том, что, возможно, это проблема потока / событий в симуляторе, где таблица обновляется слишком быстро или уведомления просто не находятся в очереди справа или что-то в этом направлении. Я решил попробовать запустить в Инструментах, чтобы узнать, могу ли я определить проблему (все CoreData, CPU Monitor, Leaks, Allocations, Thread States, Dispatch и еще пара). Каждый раз, когда я делал «первый запуск» с чистым списком, с тех пор он отлично работал. Может быть, инструменты замедляют это достаточно?

В конечном счете мне нужно протестировать устройство, чтобы получить точный тест, и если проблема не исчезнет, ​​я попробую ваше решение в принятом ответе (для создания базы SQL-Lite DB для загрузки).

PhoneC: Разработка iOS проста с помощью XCode, Swift3, UITableView, cocatouch, давайте создадим приложения для iPhone, iPad и Macbook.