Observe progress of Data download in Swift?
Don't use Data(contentsOf: url)
to make synchronous request for urls that are not local resources. You should use URLSession
.To observe the progress you need to set urlsessiondownloaddelegate https://developer.apple.com/documentation/foundation/urlsessiondownloaddelegate and to monitor the progress, use the method
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)
https://developer.apple.com/documentation/foundation/urlsessiondownloaddelegate/1409408-urlsession
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
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
}
}
How to link Firebase download file with a progress view?
Several thoughts:
- Don't download in memory and then write to disk--we have a method that downloads straight to the file system
- Attach listeners rather than a single completion handler--that way you can listen to progress updates
- Use something like MBProgressHUD to show an incremental progress bar
- No need to set the
isNetworkActivityIndicatorVisible
as we'll do that for you
Putting that together, you get something like:
// Create a reference to the file we want to download
let starsRef = storageRef.child("images/stars.jpg")
// Start the download (in this case writing to a file)
let downloadTask = storageRef.write(toFile: localURL)
// Start progress indicator
// Observe changes in status
downloadTask.observe(.progress) { snapshot in
// Download reported progress
let percentComplete = 100.0 * Double(snapshot.progress!.completedUnitCount)
/ Double(snapshot.progress!.totalUnitCount)
// Update the progress indicator
}
downloadTask.observe(.success) { snapshot in
// Download completed successfully
// Stop progress indicator
}
// Errors only occur in the "Failure" case
downloadTask.observe(.failure) { snapshot in
// An error occurred!
// Stop progress indicator
}
Showing the file download progress with NSURLSessionDataTask
You need to implement following delegates:
<NSURLSessionDataDelegate, NSURLSessionDelegate, NSURLSessionTaskDelegate>
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;
}
Related Topics
Swift: Generic Overloads, Definition of "More Specialized"
Creating a Subclass of Skshapenode
Does Swift Have Short-Circuiting Higher-Order Functions Like Any or All
Swiftui [Bug] Navigationview and List Not Showing on iPad Simulator Only
Swift Realm: After Writing Transaction Reference Set to Nil
Saving Highscores with Nsuserdefaults
Drag a Cgrect Using Uipangesturerecognizer
Swift iOS 9: Section Header Change Position After Reload Data
Swift Error: 'Sequence' Requires the Types 'T' and 'Arrayslice<T>' Be Equivalent
Swift Callkit Sometimes Can't Activate Loudspeaker After Received Call (Only Incoming Call)
Data Ranged Subscribe Strange Behavior
How to Display an Int Without Commas
Swift: Google Maps Draw Waypoint Polyline
Swiftui How to Animate Each Character in Textfield
How to Compare Range<String.Index> and Defaultbidirectionalindices<String.Characterview>