Here we are going to discuss how to download large files and save partial data even when the app is terminated and also updating the view when is in the background.
Creating an object of URLSession
Create an object of URLSession which you have to config the identifier using URLSessionConfiguration after make isDiscretionary true so that we will enable downloading with performance in the background state.
1 2 3 4 5 6 |
private lazy var urlSession: URLSession = { let config = URLSessionConfiguration.background(withIdentifier: "\(Bundle.main.bundleIdentifier ?? "").backgrouns") config.isDiscretionary = true config.sessionSendsLaunchEvents = true return URLSession(configuration: config, delegate: self, delegateQueue: nil) }() |
After that pass URL from which you want to download the using downloadTask method of URL session class
1 |
urlSession.downloadTask(with: URL(string: "your url")!) |
then file downloading will start to track the download data likes totalBytesExpectedToWrite, totalBytesWritten from that you can calculate how much data is downloaded with this delegate method
1 2 3 4 5 6 7 8 |
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) { print(totalBytesExpectedToWrite) print(totalBytesWritten) let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite) debugPrint("Progress \("") \(progress)") } |
After when your file is downloaded you can save in directory of your app.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { guard let httpResponse = downloadTask.response as? HTTPURLResponse, (200...299).contains(httpResponse.statusCode) else { print ("server error") return } do { let documentsURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) let savedURL = documentsURL.appendingPathComponent( "\(randomString(length: 2)).pdf") print(location) print(savedURL) try FileManager.default.moveItem(at: location, to: savedURL) } catch { print ("file error: \(error)") } } func randomString(length: Int) -> String { let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" let len = UInt32(letters.length) var randomString = "" for _ in 0 ..< length { let rand = arc4random_uniform(len) var nextChar = letters.character(at: Int(rand)) randomString += NSString(characters: &nextChar, length: 1) as String } return randomString } |
Suppose user put your application in background mode then handleEventsForBackgroundURLSession method call of the app delegate class
1 2 3 4 5 6 |
var backgroundCompletionHandler : ( () -> Void )? func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) { debugPrint("handleEventsForBackgroundURLSession: \(identifier)") backgroundCompletionHandler = completionHandler } |
And downloading is completed in background state then you have to update the view in the main thread
1 2 3 4 5 6 7 8 9 10 |
func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) { DispatchQueue.main.async { guard let appDelegate = UIApplication.shared.delegate as? AppDelegate, let backgroundCompletionHandler = appDelegate.backgroundCompletionHandler else { return } backgroundCompletionHandler() } } |
Be the first to comment.