0

I'm iOS Developer.I want to implement functionality like,there are multiple files display in UITableview with File name,UIProgressView and download button.I want to implement if user click on download button then start downloading file with updating UIProgressView value for that cell,if I click on another cell's download button then both file should be download simultaneously with downloading status. please help me if anyone have idea. here is my code

import UIKit

class PDFCell: UITableViewCell,URLSessionTaskDelegate,URLSessionDownloadDelegate {

    @IBOutlet weak var btnStartDownload: UIButton!
    @IBOutlet weak var downloadProgress: UIProgressView!
    var url:String?
    var percentageWritten: Float = 0.0
    var taskTotalBytesWritten = 0
    var taskTotalBytesExpectedToWrite = 0
    var task: URLSessionTask!
    let config = URLSessionConfiguration.background(withIdentifier: "lanet.PDFDownload")
    lazy var session: URLSession = {
        URLSession(configuration: config, delegate: self as! URLSessionDelegate, delegateQueue: OperationQueue())
    }()
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
        if totalBytesExpectedToWrite > 0 {
            let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
            DispatchQueue.main.async {
                self.downloadProgress.progress = progress
            }
            debugPrint("Progress \(downloadTask) \(progress)")
        }
    }
    override func prepareForReuse() {
        super.prepareForReuse()
        self.url = ""
    }
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
        let path = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.documentDirectory, FileManager.SearchPathDomainMask.userDomainMask, true)
        let documentDirectoryPath:String = path[0]
        let fileManager = FileManager()
        let destinationURLForFile = URL(fileURLWithPath: documentDirectoryPath.appendingFormat("/file.pdf"))
        if fileManager.fileExists(atPath: destinationURLForFile.path){
            // showFileWithPath(path: destinationURLForFile.path)
        }
        else{
            do {
                try fileManager.moveItem(at: location, to: destinationURLForFile)
                // show file
                // showFileWithPath(path: destinationURLForFile.path)
            }catch{
                print("An error occurred while moving file to destination url")
            }
        }

        debugPrint("Download finished: \(location)")
        try? FileManager.default.removeItem(at: location)
    }

    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
        debugPrint("Task completed: \(task), error: \(error)")
    }


    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

    @IBAction func btnDownloadClick(_ sender: Any) {
        let url = URL(string: self.url!)!
        let task = session.downloadTask(with: url)
        task.resume()
    }
}

} enter image description here

halileohalilei
  • 2,220
  • 2
  • 25
  • 52
Ankit Prajapati
  • 129
  • 1
  • 11
  • What exactly is wrong with the code you have right now? – halileohalilei Jan 04 '18 at 12:05
  • If i click on any cell first time it is working fine for that cell.But second time if i click on any cell it will show progress on previously selected cell(first time selected cell) – Ankit Prajapati Jan 04 '18 at 12:13
  • here is a complete demo https://www.raywenderlich.com/158106/urlsession-tutorial-getting-started – Prashant Tukadiya Jan 04 '18 at 12:16
  • **You are strongly discouraged from running URLSession related code in the view (the cell)**. Consider that the cell can be deallocated immediately and the download will run into an undefined state. This code is supposed to be executed in the controller, the model or in a separate download manager. The UI could be updated continuously with a callback closure. – vadian Jan 04 '18 at 12:42
  • @Ankit Prajapati Could you solve it ?, I'm with the same problem, if you were so kind to share your reference code. – Mario Burga Jul 22 '18 at 04:37

1 Answers1

2

Go through this tutorial for basic reference: https://www.raywenderlich.com/158106/urlsession-tutorial-getting-started

In section download progress you will see

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, 
  didWriteData bytesWritten: Int64, totalBytesWritten: Int64, 
  totalBytesExpectedToWrite: Int64) {
  // 1
  guard let url = downloadTask.originalRequest?.url,
    let download = downloadService.activeDownloads[url]  else { return }
  // 2
  download.progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
  // 3
  let totalSize = ByteCountFormatter.string(fromByteCount: totalBytesExpectedToWrite, countStyle: .file)
  // 4
    DispatchQueue.main.async {
    if let trackCell = self.tableView.cellForRow(at: IndexPath(row: download.track.index,
      section: 0)) as? TrackCell {
      trackCell.updateDisplay(progress: download.progress, totalSize: totalSize)
    }
  }
}
Abhishek Thapliyal
  • 3,497
  • 6
  • 30
  • 69