Alexander Khitev
Alexander Khitev

Reputation: 6861

how to return value after the execution of the block? Swift

I want to get a value from function. There is a block in function. When block executes the function already returns the value. I tried many different methods but they didn't help me. I used NSOperation and Dispatch. The function always returns value until execution of block.

   var superPlace: MKPlacemark!

 func returnPlaceMarkInfo(coordinate: CLLocationCoordinate2D) -> MKPlacemark? {
    let location = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
    geocoder.reverseGeocodeLocation(location) { (arrayPlaceMark, error) -> Void in
            if error == nil {
                let firstPlace = arrayPlaceMark!.first!
                let addressDictionaryPass = firstPlace.addressDictionary as! [String : AnyObject]

                self.superPlace = MKPlacemark(coordinate: location.coordinate, addressDictionary: addressDictionaryPass)
            }
        }

    return superPlace
}

Upvotes: 2

Views: 2244

Answers (2)

Swinny89
Swinny89

Reputation: 7373

You cannot simply return here as the reverseGeocodeLocation function is running asynchronously so you will need to use your own completion block:

var superPlace: MKPlacemark!

func getPlaceMarkInfo(coordinate: CLLocationCoordinate2D, completion: (superPlace: MKPlacemark?) -> ()) {
    let location = CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
    geocoder.reverseGeocodeLocation(location) { (arrayPlaceMark, error) -> Void in
        if error == nil {
            let firstPlace = arrayPlaceMark!.first!
            let addressDictionaryPass = firstPlace.addressDictionary as! [String : AnyObject]

            self.superPlace = MKPlacemark(coordinate: location.coordinate, addressDictionary: addressDictionaryPass)
            completion(superPlace: superPlace)
        } else {
            completion(superPlace: nil)
        }
    } 
}

Upvotes: 2

Duncan C
Duncan C

Reputation: 131511

This comes up over and over and over. The short answer is "you can't."

The result is not available when your function returns. The async call takes place in the background.

What you want to do is refactor your returnPlacemarkInfo function to take a completion closure.

I have been working in Objective-C lately, so my Swift is a little rusty, but it might look like this:

 func fetchPlaceMarkInfo(
  coordinate: CLLocationCoordinate2D, 
  completion: (thePlacemark: MKPlacemark?) -> () )
 {
 }

Then when you call it, pass in a completion closure that gets invoked once the placemark is available.

EDIT:

I wrote a demo project and posted it on Github that simulates handling an async network download. Take a look at

https://github.com/DuncanMC/SwiftCompletionHandlers

Specifically look at the method asyncFetchImage(), which does almost exactly what we are talking about: Uses an async method internally, and takes a completion block that it calls once the async load is done.

Upvotes: 1

Related Questions