Основные данные.Использование NSFetchedResultsController с контекстом .privateQueueConcurrencyType.Как получить данные из основного потока - PullRequest
0 голосов
/ 31 мая 2019

У меня есть приложение с табличным представлением.При запуске приложение импортирует более 100 000 строк json в CoreData.

Я использую пакеты (250 элементов) и NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType) для записи в базу данных по частям, а не для блокировки основного потока.

Эти импортированные данные должны отображаться в табличном представлении, и пользователь сможетпрокручивать представление таблицы плавно во время импорта.

Ранее я пытался использовать .mainQueueConcurrencyType для контекста для NSFetchedResultsController, но он останавливает прокрутку во время слияния из других частных контекстов. (, поскольку слияние выполняется в главном потоке ).

Я создал NSFetchedResultsController для отображения данных в табличном представлении и установил NSManagedObjectContext с concurrencyType = .privateQueueConcurrencyType.

ИтакNSFetchedResultsController вызывает func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) и func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) в фоновом потоке и изменяет свойство fetchedObjects также в фоновом потоке .

НО func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell для вызовов табличного представления из основного потока .

Таким образом, fetchedObjects может быть изменено в любое время ( фоновым потоком ) вне зависимости отосновной поток, поэтому он производит сбой .

(Например, когда fetchedObjects были удалены и теперь содержат 0 элементов, но func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int может иметь предыдущее значение fetchedObjects.count.)

Вопрос: Каксинхронизировать фоновый поток контекста CoreData и доступ к данным из основного потока TableView?

Код:

class QuakesViewController: UITableViewController {


 var tmpQuakes = [Quake]()

 var changesStarted: Bool = false {
        didSet {
            tmpQuakes = changesStarted ? dataProvider.fetchedResultsController.fetchedObjects ?? [] : []
        }
  }

 func getQuake(byIndexPath indexPath: IndexPath) -> Quake? {
    return changesStarted ? tmpQuakes[indexPath.row] : dataProvider.fetchedResultsController.fetchedObjects?[indexPath.row]
 }

 func getCount() -> Int {
     return changesStarted ? tmpQuakes.count : dataProvider.fetchedResultsController.fetchedObjects?.count ?? 0
 }
}

// MARK: - UITableViewDataSource

extension QuakesViewController {

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    guard let cell = tableView.dequeueReusableCell(withIdentifier: "QuakeCell", for: indexPath) as? QuakeCell else {
        print("Error: tableView.dequeueReusableCell doesn'return a QuakeCell!")
        return QuakeCell()
    }
    guard let quake = getQuake(byIndexPath: indexPath) else { return cell }

    cell.configure(with: quake)
    return cell
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return getCount()
}
}

// MARK: - NSFetchedResultsControllerDelegate

extension QuakesViewController: NSFetchedResultsControllerDelegate {

    /**
 Reloads the table view when the fetched result controller's content changes.
 */
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    DispatchQueue.main.sync {
        self.changesStarted = false
        self.tableView.reloadData()
    }
}

func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    DispatchQueue.main.sync {
        self.changesStarted = true
    }
}
}

Можно ли выполнить синхронизацию без дополнительных переменных (например, tmpQuakes и changesStarted)?

Та же проблема, что и: Дочерние контексты CoreData, NSFetchedResultsController и основной поток

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...