1

I have been trying for hours to get the array results values outside of the function it's created in - having defined the var as global outside and such bit it always sets to nil outside the do braces

I also tried to create a return value function but I still cannot pass the variable back as I need to return outside of the do-braces

First question here - please be gentle - I'm a newbie and completing a college project!

    func searchAPI(country: String, date: String) {
    let headers = [
        "x-rapidapi-host": "covid-19-data.p.rapidapi.com",
        "x-rapidapi-key": "9d0431109emsh8f01caba0edb8d7p16cebdjsnc69ffe8f2569"
    ]
    var request = URLRequest(url: URL(string:   "https://covid-19-data.p.rapidapi.com/report/country/name?date-format=YYYY-MM-DD&format=json&date=\(date)&name=\(country)")! as URL,
        cachePolicy: .useProtocolCachePolicy,
        timeoutInterval: 10.0)

    request.httpMethod = "GET"
    request.allHTTPHeaderFields = headers

    let session = URLSession.shared
    let dataTask = session.dataTask(with: request) { (data, response, error) in
    guard let data = data else {
        return
    }
    do {
        let httpResponse = response as? HTTPURLResponse
        //print(httpResponse!)
        let decoder = JSONDecoder()
        let results = try decoder.decode([Covid].self, from: data)
        print(results[0].country)
        //print(results[0].provinces.count)
        //print(results[0].provinces[0])
        //print(results[0].provinces[0].active)
        }
    catch let error {
        print("\(error)")
    }
    }
    dataTask.resume()
    return
}

func formatDate(date: Date) -> String {
    let formatter = DateFormatter()
    formatter.dateFormat = "YYYY-MM-dd"
    let newDate = formatter.string(from: date)
    return newDate
    }
Piquet
  • 33
  • 3

1 Answers1

0

Here you need to use closure to get the results outside of the asynchronous call. You need to modify the function definition and use the completion closure block to send the decoded data through it like this:

func searchAPI(country: String, date: String, completion: @escaping ([Covid]) -> Void) {
    //...
    let results = try decoder.decode([Covid].self, from: data)
    completion(results)
}

Note: It would be better design to add the and Error property too since if the decoding or searchAPI fails to fetch data the error info can be used to show a message for the user. In this case you can modify the definition and completion handler like this:

func searchAPI(country: String, date: String, completion: @escaping ([Covid], Error?) -> Void) {
    //...
    if error != nil {
        completion([], error)
    }
        //...
        let results = try decoder.decode([Covid].self, from: data)
        completion(results, nil)
    //...
    } catch {
        completion([], error)
    }
}

Better approach: A modern approach is to use the Result type and use the success and failure block to handle both scenarios as @Vadian has just posted.

Frankenstein
  • 15,732
  • 4
  • 22
  • 47