0

I have some code that gets an API response and I would like to make it so the response is stored in another script because json is a local variable so I can only use the data in the getData function.

This is the code:

import UIKit

class HomeViewController: UIViewController {
    
    @IBOutlet weak var TestLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let url = """
https://api.coronavirus.data.gov.uk/v1/data?filters=areaType=nation;areaName=england&structure=%7b%22date%22:%22date%22,%22areaName%22:%22areaName%22,%22areaCode%22:%22areaCode%22,%22newCasesByPublishDate%22:%22newCasesByPublishDate%22,%22cumCasesByPublishDate%22:%22cumCasesByPublishDate%22,%22newDeathsByDeathDate%22:%22newDeathsByDeathDate%22,%22cumDeathsByDeathDate%22:%22cumDeathsByDeathDate%22%7d
"""
        getData(from: url)
        
        // Do any additional setup after loading the view.
    }
    
    func getData(from url: String) {
        guard let theURL = URL(string: url) else { print ("oops"); return }
        let getfromurl = URLSession.shared.dataTask(with: theURL, completionHandler: {data, response, error in
            guard let data = data, error == nil else{
                print("Something Went Wrong")
                return
            }
            
            //Have data
            var result: Response?
            do {
                result = try JSONDecoder().decode(Response.self, from: data)
            }
            catch{
                print("failed to convert \(error)")
            }
            
            guard let json = result else {
                return
            }
            
            print(json)
        })
        getfromurl.resume()
    }
    
    
}

struct Response: Codable {
    let data: [MyData]
}

struct MyData: Codable{
    let date: String
    let areaName: String
    let areaCode: String
    let newCasesByPublishDate: Int
    let cumCasesByPublishDate: Int?
    let newDeathsByDeathDate: Int?
    let cumDeathsByDeathDate: Int?
}
Leo Gaunt
  • 711
  • 1
  • 8
  • 29
  • 1
    What is "another script" here, outside of the HomeViewController? And you should be thinking in terms of classes and structs and not different scripts. – Joakim Danielson Feb 06 '21 at 18:29
  • Yes outside the HomeViewController, I want to be able to have it in sort of a central script where I can reference it rather than in this ViewController, I don't know how to do this API call now in a View Controller though – Leo Gaunt Feb 06 '21 at 18:31

1 Answers1

1

Swift is working with Modules. The Data structure Response will be available for you throughout your app, as it is part of it. I'd suggest extending you knowledge about how Swift is working with Modules by reading this.

As for the architecture part of the app, I would recommend on creating a separate class which will be a service that will parse and return the response to whomever is calling it. You should use completion handlers for that...

some pseudo example

final class CovidService {
    func getData(url: String, @escaping completion:((Result<Response,Error>) -> Void)) {
        // your get data function
        //.....
        guard let json = result else {
            completion(SomeError)
            return
        }
        completion(json)
    }
}

With this service, you can fetch the data in every ViewController or other entity you wish...

Some more reading that could extend you knowledge about completion handlers and services in Swift completions API services

CloudBalancing
  • 1,461
  • 2
  • 11
  • 22