0

My question is simple but after many research and tests I do not succeed to wait for a function end before continuing the flow.

Example :

print("Before stuff")
do_stuff {
    print("After stuff")
}


func do_stuff(onCompleted: () -> ()) {
    let postEndpoint: String = "http://localhost:8080/users/1234567890987654"
    guard let url = NSURL(string: postEndpoint) else {
        print("Error: cannot create URL")
        return
    }
    let urlRequest = NSURLRequest(URL: url)
    let config = NSURLSessionConfiguration.defaultSessionConfiguration()
    let session = NSURLSession(configuration: config)
    let task = session.dataTaskWithRequest(urlRequest, completionHandler: {
    (data, response, error) in
    guard let responseData = data else {
        print("Error: did not receive data")
        return
    }
    guard error == nil else {
        print("error calling GET on /users/1234567890987654")
        print(error)
        return
    }
    // parse the result as JSON
    let user: NSDictionary
    do {
        user = try NSJSONSerialization.JSONObjectWithData(responseData,
            options: []) as! NSDictionary
    } catch  {
        print("error trying to convert data to JSON")
        // Means that user does not exist
        return
    }
    print("The user is: " + user.description)
    })
    task.resume()
    onCompleted()
}

How to wait do_stuff() end before the second print?

Thanks for your help, I think I miss something.

Thomas

Thomi
  • 639
  • 2
  • 9
  • 21

2 Answers2

1

There is something fundamental that you haven't understood. It's not actually the function, which is executing. It's the closure defined inside the function. What you need to wait is the closure to be called when the request has completed. And in fact, you should not wait, but assign an another closure outside the function to be called from the closure inside the function.

print("Before stuff")
do_stuff {
    // Now the "function" has completed.
    print("After stuff")
}

func do_stuff(onCompleted: () -> ()) {
    let task = session.dataTaskWithRequest(urlRequest) { data, response, error in
        ...
        onCompleted()
    }
}
Tapani
  • 3,191
  • 1
  • 25
  • 41
  • Thank you for your answer. I just edited my code with your advices, but unfortunately I still get "After stuff" print before my "print("The user is....")" :( – Thomi Feb 04 '16 at 20:51
  • How did you edit the code? If the print line is before onCompleted call it is not possible that "After stuff" is printed before "The user is...". onCompleted must be the last line in the closure. – Tapani Feb 04 '16 at 20:53
  • Yes I got it, my onCompleted() was misplaced I just corrected it and that works fine. Thank you – Thomi Feb 04 '16 at 20:55
0

You could always use a completion handler for the do_stuff() function:

func do_stuff(completion: (() -> Void)?) -> () {
...
    if completion != nil {
        return completion!() // Return completion where you want you "after stuff" declarations to run.
    }
}

And call the function as such:

do_stuff({
    print("After stuff")
})
xoudini
  • 7,001
  • 5
  • 23
  • 37