0

I am implementing a ViewController to display a PDF previously downloaded from my server and stored locally on the device, it works correctly, but to download the PDF takes too much time and I would like to implement a progress-bar.

My code is the following, where I have tried to implement the @IBOutlet weak var downloadBar: UIProgressView! . As I get the time it takes for the download, so I eat my code reaches 100% and the download does not end yet.

class PDFViewController: UIViewController {
    @IBOutlet weak var pdfView: PDFView!

    @IBOutlet weak var downloadBar: UIProgressView!

    //*******
    var downloader = Timer()
    var minValue = 0
    var maxValue = 100
    //********

    var namePDF:String?

    override func viewDidLoad() {
        super.viewDidLoad()

        downloadBar.setProgress(0, animated: false)


        if let pdfUrl = URL(string: "https://miserver.com/\(namePDF!).pdf") {


            print(pdfUrl)

            // then lets create your document folder url
            let documentsDirectoryURL =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!

            // lets create your destination file url
            let destinationUrl = documentsDirectoryURL.appendingPathComponent(pdfUrl.lastPathComponent)
            print(destinationUrl)

            // to check if it exists before downloading it
            if FileManager.default.fileExists(atPath: destinationUrl.path) {
                print("The file already exists at path")

                /************** show pdf ****************/
                let pdfUrl = destinationUrl.path
                let rutafile = URL(fileURLWithPath: pdfUrl)
                print(pdfUrl)
                if let document = PDFDocument(url: rutafile) {
                    pdfView.autoScales = true
                    pdfView.document = document
                }
                 /************** end show pdf ****************/


                // if the file doesn't exist
            } else {
                 print("file doesn't exist")

                downloader = Timer.scheduledTimer(timeInterval: 0.06, target: self, selector: (#selector(PDFViewController.updater)), userInfo: nil, repeats: true)
                downloadBar.setProgress(0, animated: false)

                // you can use NSURLSession.sharedSession to download the data asynchronously
                URLSession.shared.downloadTask(with: pdfUrl, completionHandler: { (location, response, error) -> Void in
                    guard let location = location, error == nil else { return }
                    do {
                        // after downloading your file you need to move it to your destination url
                        try FileManager.default.moveItem(at: location, to: destinationUrl)
                        print("File moved to documents folder")

                        print("file has already been downloaded")
                        /************** show pdf ****************/
                        let pdfUrl = destinationUrl.path
                        let rutafile = URL(fileURLWithPath: pdfUrl)
                        print(pdfUrl)
                        if let document = PDFDocument(url: rutafile) {
                            self.pdfView.autoScales = true
                            self.pdfView.document = document
                        }
                        /************** show pdf ****************/

                    } catch let error as NSError {
                        print(error.localizedDescription)
                    }
                }).resume()
            }
        }



    }

@objc func updater() {

    if minValue != maxValue {
        minValue += 1
        downloadBar.progress = Float(minValue) / Float(maxValue)

        print(Float(minValue) / Float(maxValue))
    } else {
        minValue = 0
        downloader.invalidate()
    }
}

}

From already thank you very much

AlbertB
  • 637
  • 6
  • 16
  • Why are you using timer? var downloader = Timer(). Also are you facing the issue with IBOutlet or that progress is not showing? – Asim Jul 24 '18 at 22:40
  • When you want to show progress, calling `downloadTask(with:completionHandler:)` for `shared` would not be the best way. Create a `URLSession` configured with delegate and prepare delegate methods correctly, and then use `downloadTask(with:)` for the created instance. I have not enough time to write an answer, hoping you can get the right direction shown soon. – OOPer Jul 24 '18 at 22:48
  • @Asim Progress if it is displayed (the progressbar works) but my problem is the time it reaches 100 without having finished downloading the file. How do I get the time it takes to download? – AlbertB Jul 24 '18 at 22:51
  • https://stackoverflow.com/q/30047706/2303865 – Leo Dabus Jul 24 '18 at 23:10

1 Answers1

1

You can implement the URLSessionDownloadDelegate protocol. And then use the following method:

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
    if totalBytesExpectedToWrite > 0 {
        let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)

        self.downloadBar.setProgress(progress, animated: false)
    }
}

This will only update progress bar when new bytes are written. And provide an accurate estimate of your download progress. Hope this helps :)

Asim
  • 361
  • 1
  • 2
  • 12
  • How to use this URLSessionDownoadDelegate protocol? I mean which class should conform it? Could you please give a detailed answer? – Ashik Sep 25 '18 at 09:44
  • Just conform the protocol to the class you are calling it from such as the respective ViewController where you want to update the progress. And listen to the progress in the above stated function. The function will be called everytime progress is made and you can assign the updated progress to your progress bar. – Asim Oct 03 '18 at 11:52