title: How to show progress in cell?
body: <p>I use code in <code>didSelectRowAt indexPath:</code> to start download file on cell click and I use code in <code>cellForRowAt indexPath:</code> to show progress of now downloading files.</p>
  
  <pre><code>class TableViewController: UITableViewController {
  
      override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
  
          return (mainArray[buttonIndex] as AnyObject).count
      }
  
      override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; 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()
  }
  }
  </code></pre>
  
  <p>I create URLSession in <code>DownloadManager</code>:</p>
  
  <pre><code>import Foundation
  
  class DownloadManager : NSObject, URLSessionDelegate, URLSessionDownloadDelegate {
  
      static var shared = DownloadManager()
  
      typealias ProgressHandler = (Float) -&gt; ()
  
      var onProgress : ProgressHandler? {
          didSet {
              if onProgress != nil {
                  let _ = activate()
              }
          }
      }
  
      override private init() {
          super.init()
      }
  
      func activate() -&gt; 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) -&gt; ()) {
          session.getTasksWithCompletionHandler { (tasks, uploads, downloads) in
              let progress = downloads.map({ (task) -&gt; Float in
                  if task.countOfBytesExpectedToReceive &gt; 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 &gt; 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)")
      }
  
  }
  </code></pre>
  
  <p>I want to click on cell, start file download and show progress of downloading file in selected cell. I can create my progressView in <code>didSelectRowAt indexPath:</code> 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 <code>cellForRowAt indexPath:</code>.</p>
  
  <p>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?</p>
  
  <p>UPD</p>
  
  <pre><code>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 &lt;= 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"
                                      }
  
                                  }
                              }
  
  
  
  }
  </code></pre>
  
  <p><strong>UPD 1</strong></p>
  
  <pre><code>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) -&gt; Int {
  
          return 1
      }
  
      override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
  
          return (mainArray[buttonIndex] as AnyObject).count
      }
  
      override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; 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 &lt;= 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></pre>
  
  <p>Code from FirstViewController</p>
  
  <pre><code>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) -&gt; Int {
  
          return 1
      }
  
      override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
  
          return array.count
      }
  
      override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; 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) -&gt; CGFloat
      {
  
          return 165.0
      }
  
      public override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -&gt; CGFloat {
          return 12.0
      }
  
      override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -&gt; 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></pre>
  
  <p>Code from TableViewCell</p>
  
  <pre><code>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)
  
  
      }
  
  }
  </code></pre>