-1

I'm building an app that uses the Google Places API. I currently have a button that, when tapped, gets the address of the current GPS location. The code is in my view controller:

var placesClient: GMSPlacesClient?

@IBAction func buttonTapped(_ sender: AnyObject) {
    placesClient?.currentPlace(callback: { (placeLikelihoods, error) -> Void in
        guard error == nil else {
            print("Current Place error: \(error!.localizedDescription)")
            return
        }

        if let placeLikelihoods = placeLikelihoods {
            let place = placeLikelihoods.likelihoods.first?.place
            self.addressLabel.text = place?.formattedAddress!.components(separatedBy: ", ").joined(separator: "\n")
        }
    })
    print("Out of the brackets...")
}

When done this way, the function completes and "Out of the brackets..." is printed.

However, when I try moving this code out of the view controller and into a custom class and call it from the view controller, like below, everything within the "placesClient?.currentPlace(callback" block runs (and retrieves the correct address), but "Out of the brackets..." never gets printed and it never returns the value:

class LocationAPIService {
var placesClient: GMSPlacesClient? = GMSPlacesClient.shared()

func getCurrentLocation() -> GMSPlace? {
    var thisPlace: GMSPlace?

    placesClient?.currentPlace(callback: { (placeLikelihoods, error) -> Void in
        guard error == nil else {
            print("Current Place error: \(error!.localizedDescription)")
            return
        }

        if let placeLikelihoods = placeLikelihoods {
            let place = placeLikelihoods.likelihoods.first?.place
            thisPlace = place
        }
    })
    print("Out of the brackets...")
    return thisPlace
}
}

Anybody know why this might be happening?

Josh
  • 1,031
  • 2
  • 19
  • 31
  • You cannot "escape completion handler". Your second code makes no sense. The line `return thisPlace` will execute _before_ the line `thisPlace = place` ever has a chance to execute, so `thisPlace` will always be `nil` and you will always return `nil`. – matt Oct 29 '16 at 02:23

1 Answers1

0

Fixed it. Here is the code I used for the method in my LocationAPIService class:

func setCurrentLocationPlace(completion: @escaping (_ result: Bool)->()) {
    var placeFindComplete: Bool = false

    placesClient?.currentPlace(callback: { (placeLikelihoods, error) -> Void in
        guard error == nil else {
            print("Current Place error: \(error!.localizedDescription)")
            completion(true)
            return
        }

        if let placeLikelihoods = placeLikelihoods {
            let place = placeLikelihoods.likelihoods.first?.place
            self.currentPlace = place
            placeFindComplete = true
            completion(true)
        }
    })
    if (placeFindComplete == false) {
        completion(false)
    }
}

And here is the way I called it from the view controller:

locationAPIService?.setCurrentLocationPlace() { (locationFound) -> () in
        if (locationFound == true) {
//Run code here that triggers once setCurrentLocationPlace() complete.
}
Josh
  • 1,031
  • 2
  • 19
  • 31