0

I am trying to wait on an asynchronously performing class to finish before continuing but are not having luck. Key points:

  • class CLGeocoder that performs asynchronously is called from an IBAction
  • I would like to set a value in the CLGeocoder completion handler and pass it to another view controller via prepareForSegue
  • What is happening: the IBAction is finishing before the CLGeocoder completion handler finishes, so prepareForSegue is called before the value is set

I have looked at: 24725059 and especially good 25634068 but not been able to craft an answer for my situation.

Most answers say in essence to put the logic to be executed in a completion handler but the logic that I want to ultimately perform is prepareForSegue.

I am just learning, so I this could very well be due to my lack of understanding of completion handlers among other concepts.

var locationPlacemark: CLPlacemark!
@IBOutlet weak var myLocation: UITextField!

@IBAction func myButton(sender: AnyObject) {
    print("start button IBAction")
    processGeo({ (placemark, error) -> Void in
        self.locationPlacemark = placemark
        print("setting placemark")
    })
    print("end button IBAction")
}

func processGeo(getLocCompletionHandler: ((placemark : CLPlacemark?, error : NSError?) -> Void)!) {
    print("before CLGeocoder")
    CLGeocoder().geocodeAddressString(self.myLocation.text!, completionHandler: {(placemarks, error) -> Void in   // called after completes
        if((error) != nil){
            print("Error", error)
        }
        print("after CLGeocoder")
        if let placemark = placemarks?[0] {
                getLocCompletionHandler(placemark: placemark, error: error)
                print("after calling completion handler")
        }
    })
}


override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "InfoPostingMapSegue" {
        let vc = segue.destinationViewController as! InfoPostingMapViewController
        print("in prepareForSegue")
        vc.locationPlacemark = locationPlacemark
    }
}

The console prints are:

start button IBAction
before CLGeocoder
end button IBAction
in prepareForSegue
after CLGeocoder
setting placemark
after calling completion handler
Community
  • 1
  • 1
  • Have you connected a segue to the button action? – luk2302 Dec 23 '15 at 23:01
  • 1
    Yes, you need to perform the segue when the glcoder has finished with `performSegueWithIdentifier` rather than using a segue action on the button itself – Paulw11 Dec 24 '15 at 00:16
  • Then how do I pass data to the receiving vc? I understand that I can use "sender" but that seems not too nice? I could save the data as a global variable or such but still run into the issue that the data will be saved in the completion controller after the IBAction method has completed? Maybe I am being obtuse. – heybrooksie Dec 24 '15 at 01:41
  • The segue is connected to the button action, which is what kicks off the prepareForSegue method when the IBAction method completes. – heybrooksie Dec 24 '15 at 01:42
  • Regarding my first comment about passing data to the vc when using performSegueWithIdentifier - I have may have been too quick. A global variable or class may work, did not test that. I was trying to avoid using a global variable or class, maybe that is the only answer if a method can not be set up to wait for a completion handler to complete. – heybrooksie Dec 24 '15 at 02:53

0 Answers0