I'm very new to swift, so I will probably have a lot of faults in my code but what I'm trying to achieve is send a GET request to a server with paramters inside a function. I want to use the array I receive from the server in my viewdidload and in other functions but cant seem to find a way to store the array so i can use it. in my function it is filled, but out of my function it is empty
var scenarioArray: Array<Any> = []
let idPersoon = UserDefaults.standard.object(forKey: "idPersoon") as! String
override func viewDidLoad() {
super.viewDidLoad()
ScenarioArray()
print(scenarioArray)
print(self.scenarioArray)
}
func ScenarioArray() {
var request = URLRequest(url: URL(string: "http://dtsl.ehb.be/app&web/ios_php/getAllScenariosByPersoon.php?persoonID="+idPersoon)!)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { // check for fundamental networking error
print("error=\(error)")
return
}
do {
if let jsonResult = try JSONSerialization.jsonObject(with: data, options: []) as? NSDictionary {
self.scenarioArray = (jsonResult["Scenarios"] as! NSArray) as! Array<Any>
print("ASynchronous\(self.scenarioArray)")
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
task.resume()
}
Your "problem" is that you are trying to GET data from a server, meaning that you are doing a network call.
Now...you don't know how long that network call will take when you launch it, if you are on a good network then it might be fast, but if you are on 3G network it might take a while.
If the call to your server was done synchronously, the result would be that each and every time you'd try to fetch data your code would focus on doing just that, meaning that nothing else would go on... that is not what you want :)
Instead, when you use
URLSession
, and calltask.resume()
that method is executed asynchronously, meaning that it starts on another thread in the background where it will fetch data.In the meantime, your main thread is free to handle UI rendering and so on. At some point in the near future your network call finishes and you now have valid data and must inform whoever needs to know.
So when you do a call to dataTask(with: completionHandler:), what you are actually saying is something along the lines of:
"hey...go fetch this data in the background please, and when you're done, I'd like to execute the code I've passed you here in the
completionHandler
with the parameters you tell me about".Hope that makes just a little sense :)
Now...you have this code:
That last part of the function call (
{ data, response, error in...
) is thecompletionHandler
, which is not executed straight away. It is not executed until the retrieval of data has completed.And therefore when you do a call to your
ScenarioArray()
function inviewDidLoad
, what will happen is that the asynchronous call to fetch data will start in the background and yourviewDidLoad
will continue what it is doing, meaning that when you say:then you can not expect
scenarioArray
to be populated yet as yourtask
is busy fetching that data in the background.So...what you need to do, as @vadian says, is to update your UI once the data has been fetched, meaning, in the
completionHandler
.Hope that makes sense and helps you.