0

I am trying to grab the response after making a post request and store that into a variable in this fashion:

var databaseId:String = ""


Alamofire.request(url, method: post, parameters: paramters).responseJSON { response in
    let jsonData = JSON(data: response.data!)
    self.databaseId = jsonData["id"].stringValue
    //databaseId has the right value in here but when I try to use it out side of this request it does't retain its value
  }

 print(databaseId) //will be ""

I understand why this is happening. The request is still being made at the time this print statement is being executed so it is still set to its default value. Is there a work around anybody has figured out for this? I've tried using completion handlers, enclosing the request body in a main thread block, but nothing works. If anybody knows a solution I would really appreciate it.

user3776662
  • 199
  • 1
  • 10
  • 1
    Using a completion handler *is* the correct solution: http://stackoverflow.com/questions/27390656/how-to-return-value-from-alamofire. – Martin R Mar 11 '17 at 21:15
  • If you understand what's happening, then you know that moving the `print()` into the completion handler will make it print the correct value. So presumably you're trying to achieve something where doing this isn't possible, but you haven't described what it is you are trying to achieve. Please describe what you're trying to achieve, because as it stands, you're not describing a problem, so there's no solution. – Jim Mar 11 '17 at 21:30
  • I am trying to update the value of databaseId to whatever the server responds back with so I can use it later in the program. databaseId is a global variable in this view controller, I want to be able to access it when I need to. – user3776662 Mar 11 '17 at 21:40

1 Answers1

0

"I understand why this is happening."

Clearly, you don't understand. (I don't mean to be snarky, but you are missing the essential point about async functions.)

In an async call like AlamoFire.request, you make the call and pass in a closure that will get run once the request is complete.

func fetchDataBaseID(myFunctionClosure: ()-> Void ) {
  //Step 1.
  Alamofire.request(url, method: post, parameters: paramters).responseJSON {
    //Step 3.
    response in
      let jsonData = JSON(data: response.data!)
      self.databaseId = jsonData["id"].stringValue
      //databaseId has the right value in here 
      //but when I try to use it out side of this request it does't retain its value
      //Put your code that needs the results here:
      //Step 4.
      myFunctionClosure() //Uses databaseID
    }

//Step 2.
print(databaseId) //will be ""

I've added step numbers above. In step 1, we're about to submit the AlamoFire.request() command.

Next step 2 executes. At that point, the AlamoFire request is still pending and the data is not available. The print statement shows no databaseId, but that's normal.

At some future time, perhaps 2 seconds later, perhaps 30 seconds later, after your program is off doing something else, the request finishes loading. At that point. AlamoFire takes the closure you gave it in step 1, and runs that code. NOW the code at step 3 runs.

Finally, invoke a closure that you pass into your function, that will run when your data is available.

You'd use the function above like this:

fetchDatabaseID() {
  print("database ID = \(self. databaseId)")
}
Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • Thank you. Although the slightly rude comment. This helped. Was a little confused on the exact syntax for completion handlers – user3776662 Mar 11 '17 at 22:48
  • My comment wasn't meant to be rude, but when I reviewed my post it sounded that way. My apologies. Async functions are counterintuitive, and until you get it you won't be able to use them correctly. – Duncan C Mar 11 '17 at 23:39