Привет! Я перешел от использования NSKeyedArchiver
к использованию CoreData
Меня заинтересовало класс NSFetchedResultsController
и его преимущества с моим приложением UITableView
.
.менеджер загрузок, который должен постоянно обновлять UITableViewCell до тех пор, пока он не завершит загрузкупроцесс загрузки иногда обновляется, иногда обновляет часть, а иногда - нет
Но процесс загрузки, безусловно, происходит.вот мой код.
NSFetchedResultsController
реализован в классе модели, который является singleton
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
}
}
}
}
RCDownload обновляется с использованием URLSession
didWriteData
метода
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: пожалуйста, если какой-либо код все еще необходим, просто дайте мне знатьобновить.