Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

ios

swift

swift2

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
}
like image 350
Alexander Khitev Avatar asked Dec 11 '25 23:12

Alexander Khitev


2 Answers

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)
        }
    } 
}
like image 195
Swinny89 Avatar answered Dec 13 '25 14:12

Swinny89


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.

like image 35
Duncan C Avatar answered Dec 13 '25 14:12

Duncan C



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!