Get Progress from Datataskwithurl in Swift

get progress from dataTaskWithURL in swift

you can use this code for showing download process with progress bar with its delegate functions.

import UIKit

class ViewController: UIViewController,NSURLSessionDelegate,NSURLSessionDataDelegate{

@IBOutlet weak var progress: UIProgressView!

var buffer:NSMutableData = NSMutableData()
var session:NSURLSession?
var dataTask:NSURLSessionDataTask?
let url = NSURL(string:"http://i.stack.imgur.com/b8zkg.png" )!
var expectedContentLength = 0


override func viewDidLoad() {
super.viewDidLoad()
progress.progress = 0.0
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
let manqueue = NSOperationQueue.mainQueue()
session = NSURLSession(configuration: configuration, delegate:self, delegateQueue: manqueue)
dataTask = session?.dataTaskWithRequest(NSURLRequest(URL: url))
dataTask?.resume()

// Do any additional setup after loading the view, typically from a nib.
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveResponse response: NSURLResponse, completionHandler: (NSURLSessionResponseDisposition) -> Void) {

//here you can get full lenth of your content
expectedContentLength = Int(response.expectedContentLength)
println(expectedContentLength)
completionHandler(NSURLSessionResponseDisposition.Allow)
}
func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) {


buffer.appendData(data)

let percentageDownloaded = Float(buffer.length) / Float(expectedContentLength)
progress.progress = percentageDownloaded
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
//use buffer here.Download is done
progress.progress = 1.0 // download 100% complete
}
}

Showing the file download progress with NSURLSessionDataTask

You need to implement following delegates:

Also need to create two properties:

@property (nonatomic, retain) NSMutableData *dataToDownload;
@property (nonatomic) float downloadSize;

- (void)viewDidLoad {
[super viewDidLoad];

NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];

NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];

NSURL *url = [NSURL URLWithString: @"your url"];
NSURLSessionDataTask *dataTask = [defaultSession dataTaskWithURL: url];

[dataTask resume];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
completionHandler(NSURLSessionResponseAllow);

progressBar.progress=0.0f;
_downloadSize=[response expectedContentLength];
_dataToDownload=[[NSMutableData alloc]init];
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
[_dataToDownload appendData:data];
progressBar.progress=[ _dataToDownload length ]/_downloadSize;
}

Find the Download Progress of a file in swift

The progress status can be calculated in

URLSession(_:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:)

This is a one of three required methods of protocol NSURLSessionDownloadDelegate. In my case the code of the method looks like this:

func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
// println("download task did write data")

let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)

dispatch_async(dispatch_get_main_queue()) {
self.progressDownloadIndicator.progress = progress
}
}

I've created a small project, which implements three different approaches:

  • download synchronously
  • download asynchronously
  • download with progress

Check it out: http://goo.gl/veRkA7

How do I check the current progress of URLSession.dataTaskPublisher?

I mostly agree with @Rob, however you can control state of DataTask initiated by DataTaskPublisher and its progress by using of URLSession methods:

func downloadData(_ req: URLRequest) {
URLSession.shared.getAllTasks { (tasks) in
let task = tasks.first(where: { (task) -> Bool in
return task.originalRequest?.url == req.url
})

switch task {
case .some(let task) where task.state == .running:
print("progress:", Double(task.countOfBytesReceived) / Double(task.countOfBytesExpectedToReceive))
return
default:
self.cancelToken = URLSession.shared.dataTaskPublisher(for: req).sink { /* ... */ }
}
}
}

Is it possible to use URL session delegate method for progress and completion handler for completion? Or better option?

Thanks to Faysal Ahmed, I managed to find the following solution that worked. This allowed me to track my progress to update UI whilst also using a completion handler.

    observation = task.progress.observe(\.fractionCompleted) { progress, _ in
DispatchQueue.main.async(execute: {
self.globalScrollTitle.mainprogress = CGFloat(progress.fractionCompleted)
})
if progress.fractionCompleted == 1 {
completion()
}
}

My download func now looks like this:

func download(url: String, fileName: String, completion: @escaping () -> Void) {
let myUrl = URL(string: url)
let request = URLRequest(url:myUrl!)
let config = URLSessionConfiguration.default
let operationQueue = OperationQueue()
let session = URLSession(configuration: config, delegate: nil, delegateQueue: operationQueue)

let task = session.dataTask(with: request) { (data, response, error) in
guard error == nil else {
print(error!)
return
}
// Success
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
print("Success: \(statusCode)")
}

do {
let documentFolderURL = try FileManager.default.url(for: .downloadsDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
let fileURL = documentFolderURL.appendingPathComponent(fileName)
try data!.write(to: fileURL)

DispatchQueue.main.async {

if FileManager.default.fileExists(atPath: fileURL.path) {
print("file present!") // Confirm that the file is here!
}
}

} catch {
print("error writing file \(error)")
}
}

observation = task.progress.observe(\.fractionCompleted) { progress, _ in
DispatchQueue.main.async(execute: {
self.globalScrollTitle.mainprogress = CGFloat(progress.fractionCompleted)
})
if progress.fractionCompleted == 1 {
completion()
}
}

task.resume()
}
}


Related Topics



Leave a reply



Submit