首页 > 解决方案 > NSFetchedResultsController 没有持续更新

问题描述

嗨,我已经从使用NSKeyedArchiver转移到使用CoreData

我之所以感兴趣,是因为该NSFetchedResultsController课程及其对UITableView.

我的应用程序是一个下载管理器,它必须不断更新 UITableViewCell 直到它完成下载

不幸的是,在实现此行为后,我的表格视图偶尔会更新数据,它会像这样打开我的表格UITableView,其中包含有关特定下载过程的信息,有时它会不断更新,有时它会更新一部分,有时它根本不会

但可以肯定的是,下载过程正在发生。这是我的代码。

在作为单例NSFetchedResultsController的模型类中实现

    lazy var fetchedResultsController: NSFetchedResultsController<RCDownload> = {

    let request: NSFetchRequest<RCDownload> = RCDownload.fetchRequest()
    let sortDiscriptor = NSSortDescriptor(key: #keyPath(RCDownload.startDate), ascending: false)
    request.sortDescriptors = [sortDiscriptor]
    let fetchedResultsController = NSFetchedResultsController(fetchRequest: request, managedObjectContext: sharedCoreDataController.getContext(), sectionNameKeyPath: nil, cacheName: nil)

    do {
        try fetchedResultsController.performFetch()
    } catch {
        fatalError("failed to fetch downloads")
    }

    return fetchedResultsController
}()

那么UITableView代码是这样的

    override func viewDidLoad() {
    super.viewDidLoad()

    self.navigationController!.navigationBar.prefersLargeTitles = true
    sharedDownloadController.fetchedResultsController.delegate = self
}

    func configureCell(tableView: UITableView, cellForRowAt indexPath: IndexPath) {

    guard let cell = tableView.cellForRow(at: indexPath) as? RCDownloadTVCell else {
        return
    }
    let download = sharedDownloadController.fetchedResultsController.object(at: indexPath)
    let downloadState = download.descriptionAsState()
    let downloaded = Double(download.downloadedBytes) / 1000000
    let downloadSize = Double(download.fileSize) / 1000000
    if downloaded > 0 {
        cell.fileDescription.text = String(format: "%.1fMB of %.1fMB", downloaded, downloadSize)
    } else {
        cell.fileDescription.text = String("Loading...")
    }
    cell.fileName.text = download.fileName
    cell.progressView.setProgress(download.progressPercentage, animated: false)

    DispatchQueue.main.async {
        switch downloadState {
        case .downloading:
            cell.actionButton.tintColor = UIColor.blue
            cell.actionButton.setTitle("Pause", for: [])
        case .suspended:
            cell.actionButton.tintColor = UIColor.blue
            cell.actionButton.setTitle("Resume", for: [])
        case .cancelled:
            cell.actionButton.tintColor = UIColor.red
            cell.actionButton.setTitle("Resume", for: [])
        case .finished:
            cell.actionButton.tintColor = UIColor.red
            cell.actionButton.setTitle("Done", for: [])
        }
    }
}

extension RCDownloadsTVC: NSFetchedResultsControllerDelegate {

func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    DispatchQueue.main.async {
        self.tableView.beginUpdates()
    }
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
    DispatchQueue.main.async {
        self.tableView.endUpdates()
    }
}

func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {

    DispatchQueue.main.async {
        switch type {
        case .insert:
            guard let newIndexPath = newIndexPath else {
                fatalError()
            }
            self.tableView.insertRows(at: [newIndexPath], with: .right)
            self.reloadData()
            break
        case .update:
            guard let indexPath = indexPath else {
                fatalError()
            }
            self.configureCell(tableView: self.tableView, cellForRowAt: indexPath)
            break
        case .move:

            break
        case .delete:
            guard let indexPath = indexPath else {
                fatalError()
            }
            self.tableView.deleteRows(at: [indexPath], with: .left)
            break
        }
    }
}

}

正在使用URLSession didWriteData方法更新 RCDownload

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {

    let predicate = NSPredicate(format: "taskIdentifier == %d", Int16(downloadTask.taskIdentifier) as CVarArg)
    let downloads = self.fetchDownloadsWith(predicate: predicate)
    if downloads.isEmpty != true {
        let download = downloads[0]
        if let fileName = downloadTask.response?.suggestedFilename {
            download.fileName = fileName
        } else {
            download.fileName = downloadTask.response?.url?.lastPathComponent
        }
        download.fileSize = totalBytesExpectedToWrite
        download.downloadedBytes = totalBytesWritten
        download.progressPercentage = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
    }
}

PS:如果仍然需要任何代码,请告诉我更新。

标签: iosswiftcore-datansfetchedresultscontroller

解决方案


推荐阅读