0

I understand how completion handlers work, but im a bit confused on the syntax. Below is a function that, given a username, calls a parse query to find out the corresponding userId. The query ends after the function is returned (so it returns nil), which is why we need the completion handler. How do i implement it?

func getUserIdFromUsername(username: String) -> String {
    var returnValue = String()
    let query = PFQuery(className: "_User")
    query.whereKey("username", equalTo: username)
    query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
        if let objects = objects {
            for object in objects {
                returnValue = object.objectId!
            }
        }
    }
    return returnValue

}

NOTE: I know examples similar to this exist, but they are either not swift, or extremely lengthy. This is a short and concise version that contains Parse.

rohaldb
  • 589
  • 7
  • 24
  • It looks like the possible duplicate is about asynchronous operations in JavaScript, not Swift. – twernt Feb 02 '16 at 19:57
  • 2
    @twernt My bad :) Here are some other samples: http://stackoverflow.com/questions/26569724/nsurlconnection-sendasynchronousrequest-cant-get-variable-out-of-closure/26569930#26569930 http://stackoverflow.com/questions/24792872/getting-data-out-of-completionhandler-in-swift-in-nsurlconnection http://stackoverflow.com/questions/32509392/how-to-return-values-from-hanekes-async-fetch-method http://stackoverflow.com/questions/25956445/handle-json-response-with-alamofire-in-swift – CouchDeveloper Feb 02 '16 at 21:00
  • There are virtually hundreds of these questions - pretty much all are language agnostic. The mentioned one has a nice explanation what asynchron and synchron means and is worth a read anyway. JavaScript utilizes Promise, and Swift has that too as third party libraries. – CouchDeveloper Feb 02 '16 at 21:06

1 Answers1

2

Here's how to implement it:

func getUserIdFromUsername(username: String, completionHandler: String -> Void) {

    let query = PFQuery(className: "_User")
    query.whereKey("username", equalTo: username)
    query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
        if let objects = objects {
            for object in objects {
                completionHandler(object.objectId!)
            }
        }
    }
}

And here's how to use it:

getUserIdFromUsername("myUser") { id in
    doSomethingWithId(id)
}
marius
  • 2,077
  • 2
  • 16
  • 15
  • error: "missing return in a function expected to return string" – rohaldb Feb 02 '16 at 12:11
  • fixed, forgot to remove the return type of the function – marius Feb 02 '16 at 15:54
  • How does the solution change if the function were void rather than returning a string? I would assume the function declaration should say Void -> Void, and that the completionHandler(object.objectId!) would no longer be needed. But what about calling the function? – rohaldb Feb 05 '16 at 00:44
  • The `completionHandler` would be of type `Void -> Void` and you would call it with no parameters like `completionHandler()`. Users of that function would have to call it sort of like `doSomethingInParse("paramValue") { doSomethingWhenCompleted() }` – marius Feb 05 '16 at 14:37