17

If I create a NSURLSessionDownloadTask, and later cancel it before it finishes, the completion block still fires seemingly.

let downloadTask = session.downloadTaskWithURL(URL, completionHandler: { location, response, error in 
    ...
}

How do I check whether or not the download task was cancelled within this block so that I don't try to operate on the resulting download when there isn't one?

Doug Smith
  • 29,668
  • 57
  • 204
  • 388

1 Answers1

37

For download task, the completion handler will be called with nil value for the location and the code value of the URLError object will be .cancelled. For example:

let task = session.downloadTask(with: url) { location, response, error in
    if let error = error as? URLError {
        if error.code == .cancelled {
            // canceled
        } else {
            // some other error
        }
        return
    }
    
    // proceed to move file at `location` to somewhere more permanent
}
task.resume()

Or look for the code value of the NSError object of NSURLErrorCancelled:

let task = session.downloadTask(with: url) { location, response, error in
    if let error = error as NSError? {
        if error.code == NSURLErrorCancelled {
            // canceled
        } else {
            // some other error
        }
        return
    }
    
    // proceed to move file at `location` to somewhere more permanent
}
task.resume()

The process of casting the error parameter is the same for data tasks, as the download task above.

For Swift 2, see previous revision of this answer.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • What about for a download task? Will the location be nil? Or should I just depend on error? – Doug Smith Oct 17 '14 at 00:29
  • Yes, the `location` will be `nil`, but you can just check `error`, and if the `code` is `NSURLErrorCancelled`, you know it's been canceled for one reason or another. – Rob Oct 17 '14 at 00:56