问题描述
我使用 didSelectRowAt indexPath:
中的代码在单击单元格时开始下载文件,我使用 cellForRowAt indexPath:
中的代码来显示现在下载文件的进度.
class TableViewController: UITableViewController {覆盖 func tableView(_ tableView: UITableView, numberOfRowsInSection 部分: Int) ->整数{返回 (mainArray[buttonIndex] as AnyObject).count}覆盖 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->UITableViewCell {let cell = tableView.dequeueReusableCell(withIdentifier: String(format: "cell", indexPath.row), for: indexPath)让circularProgressViewForCell = FFCircularProgressView(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(24), height: CGFloat(24)))cell.accessoryView = circleProgressViewForCellcircleProgressViewForCell.isHidden = trueDownloadManager.shared.onProgress = { (progress) incircleProgressViewForCell.isHidden = falseOperationQueue.main.addOperation {circleProgressViewForCell.progress = CGFloat(progress)if (cell.accessoryView as!FFCircularProgressView?)?.progress == 1.0 {打印(FFCircularProgressView")(cell.accessoryView as!FFCircularProgressView?)?.circularState = .completed}}}}覆盖 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {让 url = URL(字符串:链接")!让 downloadTaskLocal = DownloadManager.shared.activate().downloadTask(with: url)下载TaskLocal.resume()}}
我在 DownloadManager
中创建 URLSession:
导入基础类 DownloadManager : NSObject, URLSessionDelegate, URLSessionDownloadDelegate {静态变量共享 = DownloadManager()typealias ProgressHandler = (Float) ->()var onProgress :ProgressHandler?{已设置{如果 onProgress != nil {让 _ = 激活()}}}覆盖私有 init() {超级初始化()}func activate() ->网址会话{让 config = URLSessionConfiguration.background(withIdentifier: "\(Bundle.main.bundleIdentifier!).background")返回 URLSession(配置:配置,委托:自我,委托队列:操作队列())}私有函数计算进度(会话:URLSession,completionHandler:@escaping(浮点数)->()){session.getTasksWithCompletionHandler {(任务、上传、下载)在let progress = downloads.map({ (task) -> Float in如果 task.countOfBytesExpectedToReceive >0 {返回浮动(task.countOfBytesReceived)/浮动(task.countOfBytesExpectedToReceive)} 别的 {返回 0.0}})完成处理程序(进度.减少(0.0,+))}}func urlSession(_ session: URLSession,downloadTask: URLSessionDownloadTask,didFinishDownloadingTo 位置:URL){让 fileName = downloadTask.originalRequest?.url?.lastPathComponent让路径 = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)让 documentDirectoryPath:String = path[0]让文件管理器 = 文件管理器()var destinationURLForFile = URL(fileURLWithPath: documentDirectoryPath.appending("/\(id)"))做 {尝试 fileManager.createDirectory(at: destinationURLForFile, withIntermediateDirectories: true, attributes: nil)destinationURLForFile.appendPathComponent(字符串(描述:文件名!))试试 fileManager.moveItem(at: location, to: destinationURLForFile)}catch(让错误){打印(错误)}}func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {如果 totalBytesExpectedToWrite >0 {如果让 onProgress = onProgress {计算进度(会话:会话,completionHandler:onProgress)}让进度 = Float(totalBytesWritten)/Float(totalBytesExpectedToWrite)debugPrint("Progress \(downloadTask) \(progress)")}}func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError 错误: 错误?) {debugPrint("任务完成:\(任务),错误:\(错误)")}}
我想点击单元格,开始文件下载并在选定的单元格中显示下载文件的进度.我可以在 didSelectRowAt indexPath:
中创建我的进度视图,但这不是最好的解决方案,因为用户可能会在我的应用程序中移动上一个或下一个控制器,或者可能在下载处于活动状态时隐藏应用程序.当用户在 TableViewController 中返回时,我会在 cellForRowAt indexPath:
中更新进度.
问题:当我开始下载文件时,我的进度未显示在所选行中.进度显示在屏幕外的行中.当我滚动 tableView 时,我看到所有单元格的进度都在变化.如何修复它并在所选单元格中显示进度?
更新
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {var item = self.items[indexPath.row]if item.downloadStatus == .inProgress ||item.downloadStatus == .completed {打印(视频已经下载")}别的 {让 url = URL(string: "link\(indexPath.row)")!let int = self.tableId + indexPath.row//table0 = 1000, table1 = 2000 等等.DownloadManager.shared.identifier = int让 downloadTaskLocal = DownloadManager.shared.activate().downloadTask(with: url)下载TaskLocal.resume()DownloadManager.shared.onProgress = { (row, progress) invar 行 = 行行 = 行 - self.tableIdDispatchQueue.main.async {让 indexpath = IndexPath.init(row: row, section: 0)let cell = self.tableView.cellForRow(at: indexpath)打印(下载单元格\(字符串(描述:单元格?.标签))")如果进度
UPD 1
导入 UIKit导入 StoreKit枚举下载状态{情况 无案件进展案件完成案例失败}结构项{变量标题:字符串!让链接 = ""var downloadStatus : DownloadStatus = .none初始化(标题:字符串){self.title = 标题}}var id = ""类 MasterViewController:UITableViewController {var mainArray:[[Any]] = []无功指数 = 0var buttonIndex = 0var 对象 = [Any]()var items = [item]()无功表Id = 0覆盖 func viewDidLoad() {super.viewDidLoad()items.append(item(title: "Video 1"))items.append(item(title: "Video 2"))items.append(item(title: "Video 3"))items.append(item(title: "Video 4"))items.append(item(title: "Video 5"))items.append(item(title: "Video 6"))items.append(item(title: "Video 7"))items.append(item(title: "Video 8"))items.append(item(title: "Video 9"))items.append(item(title: "Video 10"))items.append(item(title: "Video 11"))items.append(item(title: "Video 12"))如果按钮索引 == 0 {id = "id0"表 ID = 1000}否则如果 buttonIndex == 1 {id = "id1"表 ID = 2000}mainArray = [array0,array1,array2,array3,array4,array5,array6]NotificationCenter.default.addObserver(self, selector: #selector(self.onApplicationDidBecomeActiveNotification), name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil)}func onApplicationDidBecomeActiveNotification(通知:通知){self.tableView.reloadData()}覆盖 func viewWillAppear(_ 动画:布尔){self.tableView.reloadData()}覆盖 func viewDidAppear(_ 动画:布尔){self.tableView.reloadData()}覆盖 func didReceiveMemoryWarning() {super.didReceiveMemoryWarning()}//MARK: - 表视图数据源覆盖 func numberOfSections(in tableView: UITableView) ->整数{返回 1}覆盖 func tableView(_ tableView: UITableView, numberOfRowsInSection 部分: Int) ->整数{返回 (mainArray[buttonIndex] as AnyObject).count}覆盖 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->UITableViewCell {let cell = tableView.dequeueReusableCell(withIdentifier: String(format: "cell", indexPath.row), for: indexPath)让 item = items[indexPath.row]打印(项目.下载状态)如果 item.downloadStatus != .completed {让progressRing = FFCircularProgressView(frame: CGRect(x: 0, y: 0, width: 24, height: 24))cell.tag = indexPath.rowcell.accessoryType = UITableViewCellAccessoryType.nonecell.accessoryView = progressRing}别的 {cell.accessoryView = nil}返回单元格}覆盖 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {var item = self.items[indexPath.row]if item.downloadStatus == .inProgress ||item.downloadStatus == .completed {打印(视频已经下载")}别的 {让 url = URL(string: "link\(indexPath.row + 1).mp3")!让 int = self.tableId + indexPath.row让下载管理器 = 下载管理器()downloadManager.identifier = intdownloadManager.folderPath = id让 downloadTaskLocal = downloadManager.activate().downloadTask(with: url)下载TaskLocal.resume()downloadManager.onProgress = { (row, progress) invar 行 = 行行 = 行 - self.tableIdDispatchQueue.main.async {让 indexpath = IndexPath.init(row: row, section: 0)let cell = self.tableView.cellForRow(at: indexpath)打印(下载单元格\(字符串(描述:单元格?.标签))")如果进度
来自 FirstViewController 的代码
导入 UIKit导入 StoreKit类 TableViewController:UITableViewController {让数组 = ["","","","","","",""]覆盖 func viewDidLoad() {super.viewDidLoad()}覆盖 func viewWillAppear(_ 动画:布尔){let newBackButton = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)self.navigationItem.backBarButtonItem = newBackButtonself.tableView.reloadData()}覆盖 func didReceiveMemoryWarning() {super.didReceiveMemoryWarning()}//MARK: - 表视图数据源覆盖 func numberOfSections(in tableView: UITableView) ->整数{返回 1}覆盖 func tableView(_ tableView: UITableView, numberOfRowsInSection 部分: Int) ->整数{返回数组.计数}覆盖 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->UITableViewCell {let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as!表视图单元格cell.button.tag = indexPath.rowcell.selectionStyle = .none返回单元格}覆盖 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {}覆盖 func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) ->CGFloat{返回 165.0}public override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) ->CGFloat {返回 12.0}覆盖 func tableView(_ tableView: UITableView, viewForHeaderInSection 部分: Int) ->界面视图?{让 headerView = UIView()headerView.backgroundColor = UIColor.clear返回标题视图}//MARK: - 导航覆盖 func prepare(for segue: UIStoryboardSegue, sender: Any?) {如果(segue.destination 是 MasterViewController){如果让按钮 = 发件人为?界面按钮{(segue.destination as? MasterViewController)?.buttonIndex = button.tag}}}}
来自 TableViewCell 的代码
导入 UIKit类 TableViewCell: UITableViewCell {@IBOutlet 弱变量按钮:UIButton!覆盖 funcawakeFromNib() {super.awakeFromNib()}覆盖 func setSelected(_ selected: Bool, 动画: Bool) {super.setSelected(选中,动画:动画)}}
@Artem 我在 DownloadManager 中添加了一个属性,作为标识符"(int).这将保存 indexpath.row 值.
将此标识符值发送回 ProgressHandler 完成块.
附上具有上述更改的更新代码.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) ->UITableViewCell {let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)DownloadManager.shared.onProgress = { (row, progress) inprint("正在下载 \(row) 的进度 \(progress)")}返回单元格}覆盖 func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {让 url = URL(字符串:链接")!DownloadManager.shared.identifier = indexPath.row让 downloadTaskLocal = DownloadManager.shared.activate().downloadTask(with: url)下载TaskLocal.resume()}
在您的下载管理器中,
class DownloadManager : NSObject, URLSessionDelegate, URLSessionDownloadDelegate {
static var shared = DownloadManager()变量标识符:Int = -1typealias ProgressHandler = (Int, Float) ->()var onProgress :ProgressHandler?{已设置{如果 onProgress != nil {让 _ = 激活()}}}覆盖私有 init() {超级初始化()}func activate() ->网址会话{让 config = URLSessionConfiguration.background(withIdentifier: "\(Bundle.main.bundleIdentifier!).background")返回 URLSession(配置:配置,委托:自我,委托队列:操作队列())}私有函数计算进度(会话:URLSession,completionHandler:@escaping(Int,Float)->()){session.getTasksWithCompletionHandler {(任务、上传、下载)在let progress = downloads.map({ (task) -> Float in如果 task.countOfBytesExpectedToReceive >0 {返回浮动(task.countOfBytesReceived)/浮动(task.countOfBytesExpectedToReceive)} 别的 {返回 0.0}})完成处理程序(self.identifier,progress.reduce(0.0,+))}}func urlSession(_ session: URLSession,downloadTask: URLSessionDownloadTask,didFinishDownloadingTo 位置:URL){让 fileName = downloadTask.originalRequest?.url?.lastPathComponent让路径 = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)让 documentDirectoryPath:String = path[0]让文件管理器 = 文件管理器()var destinationURLForFile = URL(fileURLWithPath: documentDirectoryPath.appending("/\(id)"))做 {尝试 fileManager.createDirectory(at: destinationURLForFile, withIntermediateDirectories: true, attributes: nil)destinationURLForFile.appendPathComponent(字符串(描述:文件名!))试试 fileManager.moveItem(at: location, to: destinationURLForFile)}catch(让错误){打印(错误)}}func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {如果 totalBytesExpectedToWrite >0 {如果让 onProgress = onProgress {计算进度(会话:会话,completionHandler:onProgress)}让进度 = Float(totalBytesWritten)/Float(totalBytesExpectedToWrite)debugPrint("Progress \(downloadTask) \(progress)")}}func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError 错误: 错误?) {debugPrint("任务完成:\(任务),错误:\(字符串(描述:错误))")}}
更新答案
我创建了一个简单的项目来演示 UITableViewCell 上的下载进度更新.
希望这有帮助:)
I use code in didSelectRowAt indexPath:
to start download file on cell click and I use code in cellForRowAt indexPath:
to show progress of now downloading files.
class TableViewController: UITableViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (mainArray[buttonIndex] as AnyObject).count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: String(format: "cell", indexPath.row), for: indexPath)
let circularProgressViewForCell = FFCircularProgressView(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(24), height: CGFloat(24)))
cell.accessoryView = circularProgressViewForCell
circularProgressViewForCell.isHidden = true
DownloadManager.shared.onProgress = { (progress) in
circularProgressViewForCell.isHidden = false
OperationQueue.main.addOperation {
circularProgressViewForCell.progress = CGFloat(progress)
if (cell.accessoryView as! FFCircularProgressView?)?.progress == 1.0 {
print("FFCircularProgressView")
(cell.accessoryView as! FFCircularProgressView?)?.circularState = .completed
}
}
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let url = URL(string: "link")!
let downloadTaskLocal = DownloadManager.shared.activate().downloadTask(with: url)
downloadTaskLocal.resume()
}
}
I create URLSession in DownloadManager
:
import Foundation
class DownloadManager : NSObject, URLSessionDelegate, URLSessionDownloadDelegate {
static var shared = DownloadManager()
typealias ProgressHandler = (Float) -> ()
var onProgress : ProgressHandler? {
didSet {
if onProgress != nil {
let _ = activate()
}
}
}
override private init() {
super.init()
}
func activate() -> URLSession {
let config = URLSessionConfiguration.background(withIdentifier: "\(Bundle.main.bundleIdentifier!).background")
return URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue())
}
private func calculateProgress(session : URLSession, completionHandler : @escaping (Float) -> ()) {
session.getTasksWithCompletionHandler { (tasks, uploads, downloads) in
let progress = downloads.map({ (task) -> Float in
if task.countOfBytesExpectedToReceive > 0 {
return Float(task.countOfBytesReceived) / Float(task.countOfBytesExpectedToReceive)
} else {
return 0.0
}
})
completionHandler(progress.reduce(0.0, +))
}
}
func urlSession(_ session: URLSession,
downloadTask: URLSessionDownloadTask,
didFinishDownloadingTo location: URL){
let fileName = downloadTask.originalRequest?.url?.lastPathComponent
let path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let documentDirectoryPath:String = path[0]
let fileManager = FileManager()
var destinationURLForFile = URL(fileURLWithPath: documentDirectoryPath.appending("/\(id)"))
do {
try fileManager.createDirectory(at: destinationURLForFile, withIntermediateDirectories: true, attributes: nil)
destinationURLForFile.appendPathComponent(String(describing: fileName!))
try fileManager.moveItem(at: location, to: destinationURLForFile)
}catch(let error){
print(error)
}
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
if totalBytesExpectedToWrite > 0 {
if let onProgress = onProgress {
calculateProgress(session: session, completionHandler: onProgress)
}
let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
debugPrint("Progress \(downloadTask) \(progress)")
}
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
debugPrint("Task completed: \(task), error: \(error)")
}
}
I want to click on cell, start file download and show progress of downloading file in selected cell. I can create my progressView in didSelectRowAt indexPath:
but it is not the best solution because user may move on previous or next controller in my app or may hide app when downloading is active. And when user returns in TableViewController I update progress in cellForRowAt indexPath:
.
Problem: when I start downloading file my progress not display in selected row. Progress display in row outside the screen. And when I scroll tableView I see changing of progress in all cells. How to fix it and show progress in selected cell?
UPD
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var item = self.items[indexPath.row]
if item.downloadStatus == .inProgress || item.downloadStatus == .completed {
print("video already downloaded")
}
else {
let url = URL(string: "link\(indexPath.row)")!
let int = self.tableId + indexPath.row // table0 = 1000, table1 = 2000 and etc.
DownloadManager.shared.identifier = int
let downloadTaskLocal = DownloadManager.shared.activate().downloadTask(with: url)
downloadTaskLocal.resume()
DownloadManager.shared.onProgress = { (row, progress) in
var row = row
row = row - self.tableId
DispatchQueue.main.async {
let indexpath = IndexPath.init(row: row, section: 0)
let cell = self.tableView.cellForRow(at: indexpath)
print("downloading for cell \(String(describing: cell?.tag))")
if progress <= 1.0 {
let progressRing = cell?.accessoryView as! FFCircularProgressView
progressRing.progress = CGFloat(progress)
if progress == 1.0 {
item.downloadStatus = .completed
cell?.textLabel?.text = "Download Complete"
}
else {
cell?.textLabel?.text = "Download In Progress"
}
}
}
}
UPD 1
import UIKit
import StoreKit
enum DownloadStatus {
case none
case inProgress
case completed
case failed
}
struct item {
var title : String!
let link = ""
var downloadStatus : DownloadStatus = .none
init(title: String) {
self.title = title
}
}
var id = ""
class MasterViewController: UITableViewController {
var mainArray:[[Any]] = []
var index = 0
var buttonIndex = 0
var objects = [Any]()
var items = [item]()
var tableId = 0
override func viewDidLoad() {
super.viewDidLoad()
items.append(item(title: "Video 1"))
items.append(item(title: "Video 2"))
items.append(item(title: "Video 3"))
items.append(item(title: "Video 4"))
items.append(item(title: "Video 5"))
items.append(item(title: "Video 6"))
items.append(item(title: "Video 7"))
items.append(item(title: "Video 8"))
items.append(item(title: "Video 9"))
items.append(item(title: "Video 10"))
items.append(item(title: "Video 11"))
items.append(item(title: "Video 12"))
if buttonIndex == 0 {
id = "id0"
tableId = 1000
}
else if buttonIndex == 1 {
id = "id1"
tableId = 2000
}
mainArray = [array0,array1,array2,array3,array4,array5,array6]
NotificationCenter.default.addObserver(self, selector: #selector(self.onApplicationDidBecomeActiveNotification), name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil)
}
func onApplicationDidBecomeActiveNotification(notification:Notification) {
self.tableView.reloadData()
}
override func viewWillAppear(_ animated: Bool) {
self.tableView.reloadData()
}
override func viewDidAppear(_ animated: Bool) {
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (mainArray[buttonIndex] as AnyObject).count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: String(format: "cell", indexPath.row), for: indexPath)
let item = items[indexPath.row]
print(item.downloadStatus)
if item.downloadStatus != .completed {
let progressRing = FFCircularProgressView(frame: CGRect(x: 0, y: 0, width: 24, height: 24))
cell.tag = indexPath.row
cell.accessoryType = UITableViewCellAccessoryType.none
cell.accessoryView = progressRing
}
else {
cell.accessoryView = nil
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var item = self.items[indexPath.row]
if item.downloadStatus == .inProgress || item.downloadStatus == .completed {
print("video already downloaded")
}
else {
let url = URL(string: "link\(indexPath.row + 1).mp3")!
let int = self.tableId + indexPath.row
let downloadManager = DownloadManager()
downloadManager.identifier = int
downloadManager.folderPath = id
let downloadTaskLocal = downloadManager.activate().downloadTask(with: url)
downloadTaskLocal.resume()
downloadManager.onProgress = { (row, progress) in
var row = row
row = row - self.tableId
DispatchQueue.main.async {
let indexpath = IndexPath.init(row: row, section: 0)
let cell = self.tableView.cellForRow(at: indexpath)
print("downloading for cell \(String(describing: cell?.tag))")
if progress <= 1.0 {
let progressRing = FFCircularProgressView(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(24), height: CGFloat(24)))
cell?.accessoryView = progressRing
progressRing.progress = CGFloat(progress)
if progress == 1.0 {
item.downloadStatus = .completed
}
}
}
}
}
Code from FirstViewController
import UIKit
import StoreKit
class TableViewController: UITableViewController {
let array = ["","","","","","",""]
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
let newBackButton = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
self.navigationItem.backBarButtonItem = newBackButton
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
cell.button.tag = indexPath.row
cell.selectionStyle = .none
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return 165.0
}
public override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 12.0
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
let headerView = UIView()
headerView.backgroundColor = UIColor.clear
return headerView
}
// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.destination is MasterViewController) {
if let button = sender as? UIButton {
(segue.destination as? MasterViewController)?.buttonIndex = button.tag
}
}
}
}
Code from TableViewCell
import UIKit
class TableViewCell: UITableViewCell {
@IBOutlet weak var button: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
@Artem I have added a property in DownloadManager, as 'identifier' (int). This will save the indexpath.row value.
Send this identifier value back in ProgressHandler completion block.
Attached the updated code with above changes.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
DownloadManager.shared.onProgress = { (row, progress) in
print("Downloading for \(row) with progress \(progress)")
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let url = URL(string: "link")!
DownloadManager.shared.identifier = indexPath.row
let downloadTaskLocal = DownloadManager.shared.activate().downloadTask(with: url)
downloadTaskLocal.resume()
}
In your DownloadManager,
class DownloadManager : NSObject, URLSessionDelegate, URLSessionDownloadDelegate {
static var shared = DownloadManager()
var identifier : Int = -1
typealias ProgressHandler = (Int, Float) -> ()
var onProgress : ProgressHandler? {
didSet {
if onProgress != nil {
let _ = activate()
}
}
}
override private init() {
super.init()
}
func activate() -> URLSession {
let config = URLSessionConfiguration.background(withIdentifier: "\(Bundle.main.bundleIdentifier!).background")
return URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue())
}
private func calculateProgress(session : URLSession, completionHandler : @escaping (Int, Float) -> ()) {
session.getTasksWithCompletionHandler { (tasks, uploads, downloads) in
let progress = downloads.map({ (task) -> Float in
if task.countOfBytesExpectedToReceive > 0 {
return Float(task.countOfBytesReceived) / Float(task.countOfBytesExpectedToReceive)
} else {
return 0.0
}
})
completionHandler(self.identifier, progress.reduce(0.0, +))
}
}
func urlSession(_ session: URLSession,
downloadTask: URLSessionDownloadTask,
didFinishDownloadingTo location: URL){
let fileName = downloadTask.originalRequest?.url?.lastPathComponent
let path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
let documentDirectoryPath:String = path[0]
let fileManager = FileManager()
var destinationURLForFile = URL(fileURLWithPath: documentDirectoryPath.appending("/\(id)"))
do {
try fileManager.createDirectory(at: destinationURLForFile, withIntermediateDirectories: true, attributes: nil)
destinationURLForFile.appendPathComponent(String(describing: fileName!))
try fileManager.moveItem(at: location, to: destinationURLForFile)
}catch(let error){
print(error)
}
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
if totalBytesExpectedToWrite > 0 {
if let onProgress = onProgress {
calculateProgress(session: session, completionHandler: onProgress)
}
let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
debugPrint("Progress \(downloadTask) \(progress)")
}
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
debugPrint("Task completed: \(task), error: \(String(describing: error))")
}
}
UPDATED ANSWER
I have created a simple project to demonstrate the download progress update on UITableViewCell.
https://github.com/mcabasheer/table-cell-progress-bar/tree/master
Hope this helps :)
这篇关于如何在单元格中显示进度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!