Danny M Danny M - 4 months ago 30
iOS Question

Issue with global variables and Alamofire

So, I am trying to do a Alamofire request, then, I'd take the information I need from the JSON data and put it into a global variable, here's my code.

struct myVariables {
static var variableOne = ""
}


func function() {
Alamofire.request(.GET, "API URL").responseJSON { response in
if let rawJSON = response.result.value {
// Here I just take the JSON and put it into dictionaries and parse the data.
myVariables.variableOne = String("data")
}
}
}


Ok, so basically, I am trying to access variableOne's data from another Swift file. Let's say I made two Swift files and in one of those files I had a function that edited the value of global variable, in the other file, if I attempted to print that global variable, I'd see the edited value. But whenever I use Alamofire, when I try to edit a global variable, the other Swift file doesn't see the changed value. So if I tried to edit the global variable within the Alamofire request block of code, I don't see the change whenever I print the variable from another file.

If anyone knows a better way to phrase that, please do correct it.

Rob Rob
Answer

I suspect the problem isn't that you're not seeing the value change, but rather an issue arising from the fact that you're dealing with an asynchronous method. For example, when you call function, it returns immediately, but your variableOne may not be updated immediately, but rather later. I bet you're checking it before this asynchronous response closure had a chance to be called.

You wouldn't have this problem if, rather than using this "global" (which is a bad idea, anyway), you instead adopted the completion handler pattern yourself.

func function(completionHandler: (String?) -> ()) {
    Alamofire.request(.GET, "API URL").responseJSON { response in
        if let rawJSON = response.result.value {
            // Here I just take the JSON and put it into dictionaries and parse the data.
           completionHandler(String("data"))
        } else {
           completionHandler(nil)
        }
    }
}

An you'd call this like so:

function() { string in
    // use `string` here
}

// but not here, because the above closure runs asynchronously (i.e. later)

By using this completion handler pattern, we solve the "how do I know when the asynchronous method is done" problem. And by passing the necessary data back as a parameter of the closure, we can excise the use of globals, keeping the scope of our data as narrow as possible.

Clearly, you should change the parameter of the closure to match whatever is appropriate in your case. But hopefully this illustrates the basic idea.

Comments