TooManyEduardos TooManyEduardos - 6 months ago 80
iOS Question

NSURLSessionDataTask return data in completion handler, Swift 2.0

I've read several other questions about this same issue, but somehow the completion handler works different for the other answers. Also, those answers are from 2015, which makes me wonder if its specific to Swift 1.x

Anyways, here's my issue. I'm making a regular GET call and I want to return the downloaded data to the calling method. Somehow this doesn't want to work for me.

Here's the code of what I'm doing (all inside a single ViewController class):

override func viewDidLoad() {
super.viewDidLoad()

// get initial GET call
getConfigurationLink();
}

func getConfigurationLink(completionHandler:String?) -> Void
{
let collectionUrl = NSURL(string: collectionUrlString);

let configuration = NSURLSessionConfiguration.defaultSessionConfiguration();
let headers: [NSObject : AnyObject] = ["Accept":"application/json"];
configuration.HTTPAdditionalHeaders = headers;
let session = NSURLSession(configuration: configuration);

let configurationUrlTask = session.dataTaskWithURL(collectionUrl!) {(data, response, error) in

completionHandler("test")
}

configurationUrlTask.resume()
}


With this code, the line of
completionHandler("test")
fails to compile with a
Cannot call value of non-function type String?
message.

So my question are:


  1. How do I create a conpletionHandler that I can pass as argument to the method?

  2. Why is the completion handler failing?



Without a completion handler, the method just returns a null value before the network call completes, as expected.

Thanks.

Answer

In your current function definition type of completionHandler is optional String, it's not a function. If you want completionHandler to be a function that you call when data task finishes, change function definition to func getConfigurationLink(completionHandler: String? -> ()). So here completionHandler is a function that takes an optional String as parameter.

You can read on how to pass a function as a parameter type for another function (that's what you're trying to do here, you're passing completionHandler function to getConfigurationLink and then calling completionHandler when network request completes) here: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html#//apple_ref/doc/uid/TP40014097-CH10-ID166

And a little more explanation about compeletionHandlers: https://thatthinginswift.com/completion-handlers/