0

I am trying to write a function that connects to my database to get object information, then returns the value (UserObject) which is called from another class. Below is my code. My problem is that the function is returning u before the completion block is done. I am using Theo for connection to my NEO4j database.

func getUserObjectFromDB(userID: NSString)->UserObject
{
    let cyperQuery: String = "CYPHER QUERY from userID"
    let cyperParams: Dictionary<String, AnyObject> = ["user" : "UserObject"]
    let u=UserObject();

    let fetchDispatchGroup: dispatch_group_t = dispatch_group_create()
    dispatch_group_enter(fetchDispatchGroup)

    theo.executeCypher(cyperQuery, params: cyperParams, completionBlock: {(cypher, error) in
        println("response from cypher \(cypher)")
        //PARSE THE RESPONSE FROM SERVER TO GET USER OBJECT
        dispatch_group_leave(fetchDispatchGroup)
     })

    //Called After the dispatch group leaves
    dispatch_group_notify(fetchDispatchGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {

    })
   return u
Matt Winfrey
  • 23
  • 1
  • 5
  • You need to understand how the concept of asynchronous programming and threading works before you can see what is wrong with this code and how to correct it. Your code is starting another thread which is executing code in parallel. By the time your code has reached the return u statement the parallel code is still running and has not yet finished. – Gruntcakes May 20 '15 at 19:32
  • The problem is that the theo.executeCypher function is already asynchronous, so how do i get my code to wait for that response from the server to return the UserObject? – Matt Winfrey May 20 '15 at 19:40
  • I don't know theo so can't comment on how and where to use it, but typically that is what completion blocks are for. You put the code you want executed when an asynchronous function finishes inside the completion block. – Gruntcakes May 20 '15 at 20:03
  • I should add you can't just move the return statement to the completion block - it won't work, when using asynchronous programming you can't use return. Instead the completion block needs to signal to the code that calls getUserObjectFromDB that the operation has finished. How this is done depends on your design and what you want to do, options are use another block, a delegate, using the notification center to post a broadcast .... When you use asychronicity your approach and design has to accommodate that. – Gruntcakes May 20 '15 at 20:13
  • Thank you so much, i am trying to implement that now. I am calling the function from an Objective-C function, so i am trying to learn how to use completion blocks in both Swift and Objective-C to properly implement them. Can you help with this. I have been stuck for hours. – Matt Winfrey May 20 '15 at 20:22
  • Not in comments like this it'll be too involved, but there's lots of previous questions and tutorials on blocks. Read a few, then if stuck post a new question with your code, but show the calling code as some context will be required. – Gruntcakes May 20 '15 at 20:27

1 Answers1

0

This is the point of GCD, it's asynchronous. You want to have something observe a variable to react to what the block does when it completes, not wait for it.

Hack Saw
  • 2,741
  • 1
  • 18
  • 33
  • Any way you can point me to a resource on how i can do this? – Matt Winfrey May 20 '15 at 19:38
  • There's more than way to do it, but I'd look for stuff on "Key Value Observing", such as https://developer.apple.com/library/mac/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html#//apple_ref/doc/uid/TP40014216-CH7-XID_8 – Hack Saw May 20 '15 at 21:05