PjotrC PjotrC - 2 years ago 134
Swift Question

Swift: How to download synchronously?

I am using following code, to download some files:

let url = NSURL(string:"https://www.example.org/")!
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
if error != nil {
NSLog("%@", "Error: \(error)");

NSLog("Loaded %i bytes", data!.length)

I want to process some of the files and quit my application after downloading. Therefore I need to know, when the download process is finished. The best would be, if there is a way to do this synchronously (no problem, if UI is blocked - it is just a spash screen with a progressbar). But as far as I understood this topic after some research, this is not possible in Swift any more...

I did wrap this code in a function, therefore I can't just add some code after the NSLog statement. What I need to know is: When did the last file finish downloading? How can I retrive this information?

EDIT: This code did work for me (but be aware, its deprecated!):

// download file synchonously ////////////////////////////////////////////////////
func downloadSync(fromURL: String, toPath: String) {
let request = NSURLRequest(URL: NSURL(string: fromURL)!)
var response: NSURLResponse?
do {
let data = try NSURLConnection.sendSynchronousRequest(request, returningResponse: &response)
data.writeToFile(toPath, atomically: true)
} catch {
print("Error while trying to download following file: " + fromURL)

Answer Source

After you invoke task.resume(), the download starts.

When the download does complete (or an error is received) the code inside the { } following dataTaskWithURL is called. That's a closure and it's called asynchronously.

let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
    // This code is executed asynchronously after data has been received

Inside the closure you receive 3 params:

  1. data: the NSData you requested
  2. response: the whole NSURLResponse
  3. error: an NSError object

These 3 values are optional, so could be nil.

E.g. error could be populated and data could be nil.

The synchronous way [DEPRECATED in iOS 9]

This approach has been deprecated in iOS 9 and you should NOT use it, however here's the code

var response: NSURLResponse?
var error: NSError?
let urlData = try NSURLConnection.sendSynchronousRequest(request, returningResponse: &response)
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download