randomuser1
randomuser1

Reputation: 2803

dispatch_async and unexpected non-void return value in void function in Swift

I have a function in my appDelegate that returns user's current location.

Now I want to call it asynchronously at some other place and I did:

func handleLocation() -> CLLocation {
  let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
  dispatch_async(dispatch_get_global_queue(priority, 0)) {
    let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
    appDelegate.startGPS()
    while (!appDelegate.isLocationFixed()) {
      sleep(1)
    }
    dispatch_async(dispatch_get_main_queue()) {
      return appDelegate.getLocation()
    }
  }
}

but now this line return appDelegate.getLocation() brings me the error:

unexpected non-void return value in void function

I don't know too much about threads in Swift yet, could you help me with fixing this issue?

Upvotes: 1

Views: 2313

Answers (1)

GetSwifty
GetSwifty

Reputation: 7756

The problem is

dispatch_async(dispatch_get_global_queue(priority, 0)) {

and

dispatch_async(dispatch_get_main_queue()) {

are actually creating closures/functions, so any code within them will relate to that function, not

func handleLocation() -> CLLocation {

If you're doing an asynchronous operation within a function, you can't really have a return statement after the asynchronous operation is completed. Instead, you should use a completion handler in your function. e.g.:

func aSyncFunction(completionHandler: (AnyObject) -> ()) {

    //do async opporation

    completionHandler("finished") // call the completion block when finished
}

Here's how I would implement it for your use case:

func handleLocation(completionBlock: (CLLocation?) -> ()) {

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {

        guard let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate else {
            dispatch_async(dispatch_get_main_queue()) {
                completionBlock(nil)
            }
            return
        }
        appDelegate.startGPS()
        while (!appDelegate.isLocationFixed()) {
            sleep(1)
        }
        dispatch_async(dispatch_get_main_queue()) {
            completionBlock(appDelegate.getLocation())
        }
    }
}

example usage:

handleLocation { (location: CLLocation?) in
    if let location = location {
         //use valid location
    }
}

Upvotes: 4

Related Questions