So this code works for me in playground but for some reason URLSession.shared.dataTask(...
doesn't call my flask API that I'm currently locally running. Any idea on what's wrong? So far I'm only concerned on why it does not enter the do{
in my project but it works properly in playground.
func getWords() -> [Word]{
var words = [Word]()
let url = URL(string: self.url)
let request = URLRequest(url: url!)
let group = DispatchGroup()
print("XD")
URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in
do {
print("A")
if let data = data{
print("B")
if let decodedResponse = try? JSONDecoder().decode([Word].self, from: data){
group.enter()
DispatchQueue.main.async(){
words = decodedResponse
print("C")
print(words)
group.leave()
}
}
}
print("DD")
} catch {
print("Words.swift Error in try catch")
}
group.enter()
}).resume()
group.leave()
group.notify(queue: DispatchQueue.main, execute: {
print(words)
})
print("ASDASD WORDS: \(words)")
for _ in 1 ... 4 {
// - to make sure there aren't duplicates -
var wordId:Int = Int.random(in: 0..<words.count)
while randomIds.contains(wordId){
wordId = Int.random(in: 0..<words.count)
}
randomIds.append(wordId)
}
//returns 4 words
return words
}
You aren't using DispatchGroup
correctly; You should call enter
before you start the asynchronous work and leave
once it is complete. You can then use notify
to perform some operation.
However, you don't really need a DispatchGroup
in this situation; You have that because you are trying to turn an asynchronous operation into a synchronous one;
The correct approach is to accept that the operation is asynchronous and it isn't possible for this function to return
[Word]
. You will need to refactor the function to accept a completion handler closure and invoke that with the result.
Something like this:
func getWords(completionHandler:@escaping (Result<[Word], Error>) -> Void) -> Void{
var words = [Word]()
let url = URL(string: self.url)
let request = URLRequest(url: url!) // Note you should use a guard and call the completion handler with an error if url is `nil`
URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in
if let error = error {
completionHandler(.failure(error))
} else {
do {
if let data = data {
let words = try JSONDecoder().decode([Word].self, from: data)
completionHandler(.success(words))
} else {
// TODO call completionHander with a .failure(SomeError)
}
} catch {
completionHandler(.failure(error))
}
}
}).resume()
}
Then you can call it:
getWords() { result in
switch result {
case .success(let words):
print(words)
case .failure(let error):
print(error.localizedDescription)
}
}