'How to return a value from a void closure in Swift?

I have a function that queries a certain user in order to access an array of that user. I returns the user and I can access their array. However, the call is asynchronous and what is being returned is nil. The function over all has a completion handler, however, inside there is a query call and by default that query returns Void.

    func _getAllMatches(completionHandler: ((UIBackgroundFetchResult) -> Void)!) -> Int{
    var toReturn = [GTLUserUser]()
    let query = GTLQueryUser.queryForUserList()
    query.userBucket = "messages-20-messagestabletes-1465782960"
    service.executeQuery(query, completionHandler: {(ticket, response, error) -> Void in
        if error != nil{
            self._showErrorDialog(error)
            return
        }
        else{
            let userCollection = response as! GTLUserCollection
            if let newUsers = userCollection.items() as? [GTLUserUser]{
                toReturn = newUsers
                completionHandler(UIBackgroundFetchResult.NewData)

            }
        }
    })

return toReturn[0].likedArray.count
}

How do I wait for this query to return and assign to "toReturn" so that it will actually return something instead of returning nothing.



Solution 1:[1]

You can add an intermediate completionHandler. Cleaner that way. Just an example here:

func application(application: UIApplication!, performFetchWithCompletionHandler completionHandler: ((UIBackgroundFetchResult) -> Void)!) {
    Use_it_here() {
        completionHandler(UIBackgroundFetchResult.NewData)
        println("Background Fetch Complete")
    }
}

func Use_it_here(completionHandler: (() -> Void)!) {
    //....
    //DO IT
    //....
    completionHandler()
}

Solution 2:[2]

So since I was trying to query data into a tableview, my solution was to query the data, then simply reload the data. Very simple, no need for completion handlers

func getMathces(){
    let query = GTLQueryUser.queryForUserList()
    query.userBucket = "bucketname"
    service.executeQuery(query, completionHandler: {(ticket, response, error) -> Void in
        if error != nil{
            self._showErrorDialog(error)
            return
        }
        else{
            let userCollection = response as! GTLUserCollection
            if let newUsers = userCollection.items() as? [GTLUserUser]{
                for mat in newUsers[0].likedArray{
                    let name: String = (mat as? String)!
                    self.matches.append(name)
                }
            }
        }
        self.tableView.reloadData()
    })
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Mtoklitz113
Solution 2 Adrian Humphrey