janson
janson

Reputation: 693

Return value from dispatch_group_notify

I am trying to retrieve information from a MySQL database and process the data. The problem is that the retrieval is done via NSURLSessions asynchronously and updates/console output is printed before the data returns.

I've solved the above problem partially by using dispatch_group_enter/dispatach_group_leave with dispatch_group_notify. Using this setup solves console output, but I cannot pass the value (my understanding is that I cannot make a return statement inside the dispatch_group_notify closure)

Setup:

MySQLCommunications.swift:

Class DBcom {
  var dbGetQueue = dispatch_group_create()

  func getMaxValue () -> Int {
    var neverGetsFilled = getDBdata()
    //process the self.DBTaskResults to extract Int (not neverGetsFilled)
    dispatch_group_notify(self.dbGetQueue, dispatch_get_main_queue(), {
      //1. Can print result here ok
      //2. Cannot return result inside closure.
    }
    return result
  }

  func getDBData () ->NSData {
    dispatch_group_enter(self.dbGetQueue)
    let getDBTask = NSURLSession.sharedSession().dataTaskWithRequest(urlRequest,
      completionHandler: {(reqData,reqResponse, reqError) -> Void in
      self.DBTaskResults = reqData
      dispatch_group_leave(self.dbGetQueue)
    })
    getDBTask.resume()
    return self.DBTaskResults
  }
}

TempTestController.swift:

class TempTestViewController: UIViewController {

  @IBAction func TestButtonPressed(sender: AnyObject) {
    let testDB = DBcom()
    var maxfloor = testDB.getMaxValue()
    println(maxfloor) //this is empty
  }
}
  

I am trying to keep everything related to retrieving data from the database inside "MySQLCommunications.swift" with functions returning relevant data. However:

var myEmptyDBReturn = testDB.getMaxValue()

is empty. I can use a global variable declared above the @UIApplicationMain line in AppDelegate.swift and do:

globalVar = getMaxValue.processed_results //done inside dispatch notify in DBcom.getMaxValue

to get the value outside of MySQLCommunications.swift, but it doesn't solve the timing issue. Essentially, I would like to know how to assign a value derived from an asynchronous task to some variable such that when I use that variable it has the retrieved data.

Upvotes: 3

Views: 1610

Answers (1)

Abdullah
Abdullah

Reputation: 7233

The method dispatch_group_notify() will return immediately without waiting for all the blocks in the group. The block passed to dispatch_group_notify() will get executed when all the blocks in that particular group has finished.

Either you may need to put a callback in getMaxValue() method which will get called when the notify block is executed.

OR

If you are not worried about calling thread be blocked then you could use dispatch_group_wait() like below example:

func getMaxValue () -> Int {

    var neverGetsFilled = getDBdata()
    //process the self.DBTaskResults to extract Int (not neverGetsFilled)

    dispatch_group_wait(self.dbGetQueue, DISPATCH_TIME_FOREVER)
    //You will reach here only when all the group blocks are executed.

    return result
}

Upvotes: 2

Related Questions