iOS-Swift How to update progressView - ios

I am developing an app where i am downloading data from web.
here i am using cancel button to cancel the download progress,this works fine if i am in the same view controller and if i navigate to new view controller and return back to download view controller progress view is not updating but the download is happening.
This is the code i am using to download data
func URLSession(session: NSURLSession,
downloadTask: NSURLSessionDownloadTask,
didFinishDownloadingToURL location: NSURL){
let path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let documentDirectoryPath:String = path[0]
let fileManager = NSFileManager()
let destinationURLForFile = NSURL(fileURLWithPath: documentDirectoryPath.stringByAppendingString( Variables.name ))
if fileManager.fileExistsAtPath(destinationURLForFile.path!){
print("File Already Exists")
} else {
do {
try fileManager.moveItemAtURL(location, toURL: destinationURLForFile)
print("File doesn't exists")
}catch{
print("An error occurred while moving file to destination url")
}
}
}
// 2
func URLSession(session: NSURLSession,
downloadTask: NSURLSessionDownloadTask,
didWriteData bytesWritten: Int64,
totalBytesWritten writ: Int64,
totalBytesExpectedToWrite exp: Int64){
//progressView.setProgress(Float(totalBytesWritten)/Float(totalBytesExpectedToWrite), animated: true)
print("downloaded \(100*writ/exp)")
dispatch_async(dispatch_get_main_queue(), {
self.counter = Float(100*writ/exp)
return
})
}
func URLSession(session: NSURLSession,
task: NSURLSessionTask,
didCompleteWithError error: NSError?){
downloadTask = nil
// progressView.setProgress(0.0, animated: true)
if (error != nil) {
print(error?.description)
} else {
print("The task finished transferring data successfully")
}
}
func documentInteractionControllerViewControllerForPreview(controller: UIDocumentInteractionController) -> UIViewController{
return self
}

Related

how to still show the progress of progressView after reloading the view controller?

this is my first question on swift, i couldn't really find any answer in the internet. i have a download button that download a pdf file from url, and there is a progressView that shows the progress of downloading to the user. everything works fine but when i download the file and reload the view controller the progress of progressView is resets to zero. how can i still show the progress of downloading even after reloading the viewController.
I'm passing the url from another viewController
please help me.
this is my code
class CellDetailsViewController: UIViewController , URLSessionDownloadDelegate{
var download = ""
var downloadTask : URLSessionDownloadTask!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func download(_ sender: Any) {
guard let url = URL(string: download)else {return}
let urlSession = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue())
downloadTask = urlSession.downloadTask(with: url)
downloadTask.resume()
print("downloading")
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
print("download Location", location)
let fileManager = FileManager.default
let documentPath = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
let PdfName = documentPath.appendingPathComponent("\(name).pdf")
try? fileManager.removeItem(at: PdfName)
do{
try fileManager.moveItem(at: location, to: PdfName)
}catch{
print("copy error\(error.localizedDescription)")
}
}
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.progressView.progress = progress
print(totalBytesExpectedToWrite)
if progress == 1 {
self.progressView.isHidden = true
}
}
}
}
}
You can store a static variable in a struct somewhere else. I would create a new file that you can store in a "Model" folder and do something like this:
struct staticVariableStorage {
static var fileProgress : Double = 0.0 }
and then you could access it in your code by setting a new value to
staticVariableStorage.fileProgress
This shouldn't be affected by resetting the ViewController seeing as it would be separate from the ViewController in the first place.

URLSession delegate methods not called [duplicate]

This question already has an answer here:
URLSessionDelegate Function Not Being Called
(1 answer)
Closed 4 years ago.
I download the song and then play it on the button. Everything in this part working. But I want to monitor the download indicator and pause and resume downloading. But delegate methods not called.
class ViewController: UIViewController, URLSessionDownloadDelegate, URLSessionTaskDelegate,URLSessionDelegate {
#IBOutlet weak var progressBar: UIProgressView!
let url = URL(string: "https://www.dropbox.com/s/s7zkka3at171wf8/Track01.mp3?raw=1")!
var audioPlayer : AVAudioPlayer!
var task: URLSessionDownloadTask!
let configuration1 = URLSessionConfiguration.default
var urlSession: URLSession!
let operationQueue1 = OperationQueue()
var url1 : URL!
// MARK: - Life CYcle
override func viewDidLoad() {
super.viewDidLoad()
}
// MARK: - IBActions
#IBAction func playAudio(_ sender: Any) {
do {
audioPlayer = try AVAudioPlayer(contentsOf: self.url1)
audioPlayer.play()
}
catch {
print("error")
}
}
#IBAction func pauseAudio(_ sender: Any) {}
#IBAction func downloadButton(_ sender: Any) {
guard let audioUrl = URL(string: "https://www.dropbox.com/s/s7zkka3at171wf8/Track01.mp3?raw=1") else {
return
}
// 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(audioUrl.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")
self.url1 = destinationUrl
// if the file doesn't exist
}
else {
print("0")
urlSession = URLSession(configuration: configuration1, delegate: self, delegateQueue: operationQueue1)
task = urlSession.downloadTask(with: audioUrl) { (location, response, error) in
guard
let location = location else {
return
}
do {
try FileManager.default.moveItem(at: location ,to : destinationUrl)
print("File moved to documents folder")
self.url1 = destinationUrl
}
catch let error as NSError{
print(error.localizedDescription)
}
print("1")
}
task.resume()
print("2")
}
print("3")
}
// MARK: -
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
print("fineshed download file")
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
print(totalBytesWritten)
print(totalBytesExpectedToWrite)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
print("All success")
}
}
Try this
let configuration = URLSessionConfiguration.default
let session = URLSession(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main)

UIdocumentInteractionController cant display the PDF file in swift 4

class ViewController: UIViewController,UIDocumentInteractionControllerDelegate
{
let documentInteractionController = UIDocumentInteractionController(url: URL(fileURLWithPath: path))
documentInteractionController.delegate = self
documentInteractionController.presentPreview(animated: true)
}
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController
{
return self
}
above code i try on my apps, when click left menu , not able to show the pdf file. anyone got idea ?
I am showing here an example for download pdf from url link displaying in UIdocumentInteractionController in swift 4 as per your requirement
class ExampleViewController: UIViewController, URLSessionDownloadDelegate, UIDocumentInteractionControllerDelegate {
let urlLink = "sample link";
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func btnDownArrowOnPressed(_ sender: UIButton) {
if(urlLink != nil){
if(urlLink != nil && urlLink != "Null" && urlLink != ""){
let backgroundSessionConfiguration = URLSessionConfiguration.background(withIdentifier: "backgroundSession")
backgroundSession = Foundation.URLSession(configuration: backgroundSessionConfiguration, delegate: self, delegateQueue: OperationQueue.main)
let url = URL(string: urlLink!
downloadTask = backgroundSession.downloadTask(with: url)
downloadTask.resume()
}else{
self.view.makeToast("You don't have any certificate to download.")
}
}
else{
self.view.makeToast("You don't have any certificate to download.")
}
}
func showFileWithPath(path: String){
let isFileFound:Bool? = FileManager.default.fileExists(atPath: path)
if isFileFound == true{
let viewer = UIDocumentInteractionController(url: URL(fileURLWithPath: path))
viewer.delegate = self
viewer.presentPreview(animated: true)
}
}
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("/Certificate.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")
}
}
}
// 2
func urlSession(_ session: URLSession,
downloadTask: URLSessionDownloadTask,
didWriteData bytesWritten: Int64,
totalBytesWritten: Int64,
totalBytesExpectedToWrite: Int64){
}
//MARK: URLSessionTaskDelegate
func urlSession(_ session: URLSession,
task: URLSessionTask,
didCompleteWithError error: Error?){
downloadTask = nil
if (error != nil) {
print(error!.localizedDescription)
}else{
self.view.hideToastActivity()
print("The task finished transferring data successfully")
}
}
//MARK: UIDocumentInteractionControllerDelegate
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController
{
UINavigationBar.appearance().tintColor = UIColor.white
return self
}
}
Use URL(string: path) instead of URL(fileURLWithPath: path)

Migrating code from NSURLConnection to NSURLSession [duplicate]

In the following code, the file downloads just fine. However none of the delegate methods seem to be called as I receive no output whatsoever. the progressView is not updated either. Any idea why?
import Foundation
import UIKit
class Podcast: PFQueryTableViewController, UINavigationControllerDelegate, MWFeedParserDelegate, UITableViewDataSource, NSURLSessionDelegate, NSURLSessionDownloadDelegate {
func downloadEpisodeWithFeedItem(episodeURL: NSURL) {
var request: NSURLRequest = NSURLRequest(URL: episodeURL)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config, delegate: self, delegateQueue: nil)
var downloadTask = session.downloadTaskWithURL(episodeURL, completionHandler: { (url, response, error) -> Void in
println("task completed")
if (error != nil) {
println(error.localizedDescription)
} else {
println("no error")
println(response)
}
})
downloadTask.resume()
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) {
println("didResumeAtOffset")
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
var downloadProgress = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)
println(Float(downloadProgress))
println("sup")
epCell.progressView.progress = Float(downloadProgress)
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
println(location)
}
}
From my testing, you have to choose whether you want to use a delegate or a completion handler - if you specify both, only the completion handler gets called. This code gave me running progress updates and the didFinishDownloadingToURL event:
func downloadEpisodeWithFeedItem(episodeURL: NSURL) {
let request: NSURLRequest = NSURLRequest(URL: episodeURL)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
let downloadTask = session.downloadTaskWithURL(episodeURL)
downloadTask.resume()
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) {
println("didResumeAtOffset: \(fileOffset)")
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
var downloadProgress = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)
println("downloadProgress: \(downloadProgress)")
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
println("didFinishDownloadingToURL: \(location)")
println(downloadTask)
}
From the NSURLSession documentation, here's the relevant section:
Like most networking APIs, the NSURLSession API is highly asynchronous. It returns data in one of two ways, depending on the methods you call:
To a completion handler block that returns data to your app when a transfer finishes successfully or with an error.
By calling methods on your custom delegate as the data is received.
By calling methods on your custom delegate when download to a file is complete.
So by design it returns data to either a completion handler block or a delegate. But as evinced here, not both.
Interestingly, Apple specifically explains this behavior in their NSURLSessionDataDelegate (but neither in the base delegate NSURLSessionTaskDelegate nor in NSURLSessionDownloadDelegate)
NOTE
An NSURLSession object need not have a delegate. If no delegate is assigned, when you create tasks in that session, you must provide a completion handler block to obtain the data.
Completion handler block are primarily intended as an alternative to using a custom delegate. If you create a task using a method that takes a completion handler block, the delegate methods for response and data delivery are not called.
Swift 3
class ViewController: UIViewController {
var urlLink: URL!
var defaultSession: URLSession!
var downloadTask: URLSessionDownloadTask!
}
// MARK: Button Pressed
#IBAction func btnDownloadPressed(_ sender: UIButton) {
let urlLink1 = URL.init(string: "https://github.com/VivekVithlani/QRCodeReader/archive/master.zip")
startDownloading(url: urlLink!)
}
#IBAction func btnResumePressed(_ sender: UIButton) {
downloadTask.resume()
}
#IBAction func btnStopPressed(_ sender: UIButton) {
downloadTask.cancel()
}
#IBAction func btnPausePressed(_ sender: UIButton) {
downloadTask.suspend()
}
func startDownloading (url:URL) {
let backgroundSessionConfiguration = URLSessionConfiguration.background(withIdentifier: "backgroundSession")
defaultSession = Foundation.URLSession(configuration: backgroundSessionConfiguration, delegate: self, delegateQueue: OperationQueue.main)
downloadProgress.setProgress(0.0, animated: false)
downloadTask = defaultSession.downloadTask(with: urlLink)
downloadTask.resume()
}
// MARK:- URLSessionDownloadDelegate
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
print("File download succesfully")
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
downloadProgress.setProgress(Float(totalBytesWritten)/Float(totalBytesExpectedToWrite), animated: true)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
downloadTask = nil
downloadProgress.setProgress(0.0, animated: true)
if (error != nil) {
print("didCompleteWithError \(error?.localizedDescription)")
}
else {
print("The task finished successfully")
}
}

Swift cancellation of NSOperationQueue does not work

I'm trying to cancel NSOperationQueue process using method cancelAllOperations() using swift but it does not work.
I am downloading a file from url when i cancel the download it doesn't work.
here is the code i am using:
var s = NSOperationQueue.mainQueue()
lazy var session : NSURLSession = {
let config = NSURLSessionConfiguration.ephemeralSessionConfiguration()
config.allowsCellularAccess = false
let session = NSURLSession(configuration: config, delegate: self, delegateQueue: self.s)
return session
}
override func viewDidLoad() {
progressBar.setProgress(0.0, animated: true) //set progressBar to 0 at start
}
#IBAction func cancel(sender: AnyObject) {
s.cancelAllOperations()
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten writ: Int64, totalBytesExpectedToWrite exp: Int64) {
print("downloaded \(100*writ/exp)")
dispatch_async(dispatch_get_main_queue(), {
self.counter = Float(100*writ/exp)
return
})
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) {
// unused in this example
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
print("completed: error: \(error)")
if(error != nil){
}
}
// this is the only required NSURLSessionDownloadDelegate method
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
let path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let documentDirectoryPath:String = path[0]
let fileManager = NSFileManager()
let destinationURLForFile = NSURL(fileURLWithPath: documentDirectoryPath.stringByAppendingString("Music.mp3"))
if fileManager.fileExistsAtPath(destinationURLForFile.path!){
print("File Already Exists")
}
else{
do {
try fileManager.moveItemAtURL(location, toURL: destinationURLForFile)
print("File doesn't exists")
}catch{
print("An error occurred while moving file to destination url")
}
}
}

Resources