Title: How to wait the function execution until json loaded in Swift?
Tags: arrays;json;swift;asynchronous;swift3
Question: I am getting json file from url, then, all json output will be added in a array. When I print the array, it says that array is empty, but actually array is not empty I know. If I use like: DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { }, then, I can print the array.
My code to get json and adding its values to the array:
var allTags:Array<String&gt; = []
func getJSON(getUrl:URL){
let url:URL = getUrl
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest) {
(data, response, error) in
let dataString =  String(data: data, encoding: String.Encoding.utf8)!
do {
let data = Data(dataString.utf8)
let dictionaries = (try? JSONSerialization.jsonObject(with: data)) as? [[String:Any]] ?? []
for dict in dictionaries {
let tags = dict["Tags"] as? [String] ?? []
for tag in tags {
allTags.append(tag)
}
}
}
}task.resume()
getJSON(getUrl: self.jsonUrl())
print(self.allTags.count) //it prints 0, but there are some data I know
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
print(self.allTags.count)  //it prints 168
Comment: Try using a callback

Comment: Just added answer

Comment: If you need parameters, use `(parameter1: Type1, parameter2: Type2) -> Void`

Comment: How can I do that? I have read about callback in stackoverflow, but, I couldnot implement it to my code... @Rishi

Comment: Its because your session.dataTask is asynchronous. This means that it is run in the background thread while the code below it is executed normally. The reason the `print(self.allTags.count)` doesn't work is because it is executed before any data can be retrieved from the the URL. While the `asyncAfter` call is executed half a second later which is long enough for the data to be retrieved.

Here is the accepted answer: Use a callback:
var allTags:Array<String&gt; = []
func getJSON(getUrl:URL, callback: @escaping () -&gt; Void) {
let url:URL = getUrl
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest) { (data, response, error) in
let dataString =  String(data: data, encoding: String.Encoding.utf8)!
do {
let data = Data(dataString.utf8)
let dictionaries = (try? JSONSerialization.jsonObject(with: data)) as? [[String:Any]] ?? []
for dict in dictionaries {
let tags = dict["Tags"] as? [String] ?? []
for tag in tags {
allTags.append(tag)
}
}
callback()
}
task.resume()
getJSON(getUrl: self.jsonUrl()) {
print(self.allTags.count) // Should work now

Here is another answer: var allTags:Array<String&gt; = []
func getJSON(getUrl:URL, completion: @escaping () -&gt; ()) {
let url:URL = getUrl
let session = URLSession.shared
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.cachePolicy = NSURLRequest.CachePolicy.reloadIgnoringCacheData
let task = session.dataTask(with: request as URLRequest) {
(data, response, error) in
let dataString =  String(data: data, encoding: String.Encoding.utf8)!
do {
let data = Data(dataString.utf8)
let dictionaries = (try? JSONSerialization.jsonObject(with: data)) as? [[String:Any]] ?? []
for dict in dictionaries {
let tags = dict["Tags"] as? [String] ?? []
for tag in tags {
allTags.append(tag)
}
}
completion()
}
}task.resume()
getJSON(getUrl: self.jsonUrl()) { [weak self] in
guard let strongSelf = self else { return }
print(strongSelf.allTags.count)

{'source': 'StackExchangeDataset', 'subset': 'stackoverflow.com', 'metadata': {'AnswerCount': 2, 'CommentCount': 5, 'ContentLicense': 'CC BY-SA 3.0', 'CreationDate': '2017:00:06/09/17', 'FavoriteCount': None, 'PostTypeId': 1, 'Tags': '<arrays><json><swift><asynchronous><swift3>', 'Title': 'How to wait the function execution until json loaded in Swift?', 'ViewCount': 641, 'id': 44459411, 'user_AboutMe': None, 'user_AccountId': 11078221.0, 'user_DisplayName': 'Cris Angelordan', 'user_Reputation': 61.0, 'user_Views': 3.0, 'user_id': 8134217.0}}