Tarek
Tarek

Reputation: 823

Passing in values to a closure function

Check out this code:

func getReversedGeocodeLocation(location: CLLocation, completionHandler: @escaping ()->()) {
    CLGeocoder().reverseGeocodeLocation(location, completionHandler: {(placemarks, error) -> Void in

        if error != nil {
            print("Reverse geocoder failed with error" + error!.localizedDescription)
            return
        }

        if placemarks != nil {
            if placemarks!.count > 0 {
                let pm = placemarks![0]
                if let addressDictionary: [AnyHashable: Any] = pm.addressDictionary,
                let addressDictionaryFormatted = addressDictionary["FormattedAddressLines"] {
                    let address = (addressDictionaryFormatted as AnyObject).componentsJoined(by: ", ")
                    self.addressInViewController = address
                }
                completionHandler()
            }
        } else {
            print("Problem with the data received from geocoder")
        }
    })
}

In the viewController

override func viewDidLoad() {
    var addressInViewController = String()
    getReversedGeocodeLocation(location: location, completionHandler: {
        print("After geo finished")
    })
}

This is a simple case for using closures. As you can see, when the reverse geo finishes, it updates the addressInViewController variable which is defined outside the function itself. I'm a bit confused when it comes to closures but I do know it's essentially passing in another function as a parameter, into a function. So can I pass in something like (_ String: x)->() instead of ()->() where the address variable would be populated from the main reverse geo function and passed along? I tried doing that but it says "x" is undefined. If this is achieve-able then I guess I can decouple my code in a better way using closures.

Thanks and have a great day :)

Upvotes: 0

Views: 122

Answers (1)

Usman Javed
Usman Javed

Reputation: 2455

define your methods like this

func getReversedGeocodeLocation(location: CLLocation, completionHandler: @escaping (_ value : Any)->()) {
    CLGeocoder().reverseGeocodeLocation(location, completionHandler: {(placemarks, error) -> Void in

        if error != nil {
            print("Reverse geocoder failed with error" + error!.localizedDescription)
            return
        }

        if placemarks != nil {
            if placemarks!.count > 0 {
                let pm = placemarks![0]
                if let addressDictionary: [AnyHashable: Any] = pm.addressDictionary,
                let addressDictionaryFormatted = addressDictionary["FormattedAddressLines"] {
                    let address = (addressDictionaryFormatted as AnyObject).componentsJoined(by: ", ")
                    self.addressInViewController = address
                }
                completionHandler(address)
            }
        } else {
            print("Problem with the data received from geocoder")
        }
    })
}

override func viewDidLoad() {
    var addressInViewController = String()
    getReversedGeocodeLocation(location: location, completionHandler: { (_ values : Any) in
         self. addressInViewController = values

    })
}

Make dataType of Value according to your need.

Upvotes: 1

Related Questions