ios - 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:如果仍然需要任何代码,请告诉我更新。
解决方案
推荐阅读
- encryption - 如何从 Google Cloud Storage 解密文件?
- mysql - 如何存储类似风险的游戏地图
- reactjs - 如何在 reactjs 打字稿项目中键入 `fetch().then()` 响应参数的值
- azure-devops - 是否有可能在 Azure DevOps 中创建跨项目路线图?
- salesforce - Salesforce 自定义对象:无效类型错误扬声器
- sql-server - 如何使用 T-SQL 在一个查询结果中获得多选
- python - 仅在数据框中提取最小值
- c# - 如何使用相同的过滤器同时过滤集合及其嵌套集合?
- c# - Application Insight 中的范围日志记录
- python - C++ DLL 中的 Python 对象