Reputation: 20437
I would like to separate the data processing of my NSURLSession into a separate method.
When making a URL request, I rely on the enclosing scope to provide me the user's callback
.
This works:
static func makeRequest(url: String, callback: APICallback) {
let urlObject = NSURL(string: url)
var request = createRequest(urlObject!, method: "GET") // internal
var session = NSURLSession.sharedSession()
var task = session.dataTaskWithRequest(request){
(data, response, error) -> Void in
// do some basic parsing, error checking, then...
callback(data, nil)
}
task.resume()
}
There's rather a lot of basic parsing and error checking I'd like to do at the application level, however, so I want to define and pass a function instead of a closure to the dataTaskWithRequest
method:
static func makeRequest(url: String, callback: APICallback) {
let urlObject = NSURL(string: url)
var request = createRequest(urlObject!, method: "GET") // internal
var session = NSURLSession.sharedSession()
var task = session.dataTaskWithRequest(request, completionHandler: gotResponse)
task.resume()
}
static private func gotResponse (nsdata: NSData!, response: NSURLResponse!, err: NSError!) -> Void {
// Do my parsing and handling here, instead.
// OOPS! Don't have access to the callback. :(
}
This all leads me to my question, which, despite the lengthy example, is about language features. Can I pass some captured scope to this method? In Javascript I could accomplish this using Function.prototype.bind, but I'm not sure how to do it in Swift.
Upvotes: 1
Views: 113
Reputation: 40963
This seems like a good example of when to use a curried method. Declare the function like this with a first parameter of an APICallback
. Note the brackets.
static private func gotResponse(callback: APICallback)(nsdata: NSData!, response: NSURLResponse!, err: NSError!) -> Void {
// use callback: like normal
}
Then, use it like this:
var task = session.dataTaskWithRequest(request, completionHandler: gotResponse(callback))
(apologies, the syntax might not be 100% correct since your code isn’t stand alone so I can’t test it fully)
Curried functions are a little finicky and had some bugs in 1.1 (though they got fixed in 1.2), so instead of using the language support for them, you could try hand-rolling if the above doesn’t work, something like:
static private func gotResponse(callback: APICallback) -> (nsdata: NSData!, response: NSURLResponse!, err: NSError!) -> Void {
return { data, response, error in
// put the common code, capturing callback:, in here...
}
}
Upvotes: 2