0

(seen below) This code originally was implemented with a .json text file, but now I'm trying to change it to implement with a live url and I am not sure how to make it a global variable since once you switch to the url it has the URLSession task and you have to use task.resume() to make it keep updating but then i'm not sure how I would be able to return the decodable T to the catData array as a void function. Please help Thank you!

Start of my new implementation:

import UIKit
import SwiftUI
import CoreLocation

let catData: [Cat] = load("https://tmha-backend.herokuapp.com/api/cats/")

func load<T: Decodable>(_ linkname: String) -> T {
    let url = URL(string: "https://tmha-backend.herokuapp.com/api/cats/")
    guard let requestUrl = url else {fatalError("Couldn't find \(linkname)")}
    var request = URLRequest(url: requestUrl)
    // Specify HTTP Method to use
    request.httpMethod = "GET"
    request.setValue("application/json", forHTTPHeaderField: "Accept")
    // Send HTTP Request
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
         guard let data = data else { return }
        do {
            var returnValue: Cat?
            let decoder = JSONDecoder()
            returnValue = try decoder.decode(Cat.self, from: data)
        } catch {
            fatalError("Couldn't parse \(linkname) as \(T.self):\n\(error)")
        }
    }
    task.resume()
}

original code:

import UIKit
import SwiftUI
import CoreLocation

let catData: [Cat] = load("catData.json")

func load<T: Decodable>(_ filename: String) -> T {
    let data: Data
    guard let file = Bundle.main.url(forResource: filename, withExtension: nil)
        else {
            fatalError("Couldn't find \(filename) in main bundle.")
    }
    do {
        data = try Data(contentsOf: file)
    } catch {
        fatalError("Couldn't load \(filename) from main bundle:\n\(error)")
    }
    do {
        let decoder = JSONDecoder()
        return try decoder.decode(T.self, from: data)
    } catch {
        fatalError("Couldn't parse \(filename) as \(T.self):\n\(error)")
    }
}

  • Does this answer your question? [Returning data from async call in Swift function](https://stackoverflow.com/questions/25203556/returning-data-from-async-call-in-swift-function) – Gereon May 09 '20 at 06:48

1 Answers1

0

try this: ( solution with completion block which you should use if you are loading something async in a function)

struct Cat: Codable {
    let name, gender, age, welcomeDescription: String
    let breed, itype, status, arrivalDate: String
    let arrivalDetails, medicalHistory, vaccinations: String
    let isMicrochipped: Bool
    let fleaControlDate, dewormingDate, fivFelvDate, specialNeeds: String
    let personality: [Int]
    let morePersonality, comments, personalExp: String

    enum CodingKeys: String, CodingKey {
        case name, gender, age
        case welcomeDescription = "description"
        case breed, itype, status
        case arrivalDate = "arrival_date"
        case arrivalDetails = "arrival_details"
        case medicalHistory = "medical_history"
        case vaccinations
        case isMicrochipped = "is_microchipped"
        case fleaControlDate = "flea_control_date"
        case dewormingDate = "deworming_date"
        case fivFelvDate = "fiv_felv_date"
        case specialNeeds = "special_needs"
        case personality
        case morePersonality = "more_personality"
        case comments
        case personalExp = "personal_exp"
    }
}

typealias Cats  = [Cat]

struct ContentView : View {

    @State var cats: Cats = []

  //  @State var myTask

    func load(_ linkname: String, completion:@escaping (Cats)->())  {
    let url = URL(string: "https://tmha-backend.herokuapp.com/api/cats/")
    guard let requestUrl = url else {fatalError("Couldn't find \(linkname)")}
    var request = URLRequest(url: requestUrl)
    // Specify HTTP Method to use
    request.httpMethod = "GET"
    request.setValue("application/json", forHTTPHeaderField: "Accept")
    // Send HTTP Request
    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
         guard let data = data else { return }
        do {
            var returnValue: Cats?
            let decoder = JSONDecoder()
            returnValue = try decoder.decode(Cats.self, from: data)
            completion(returnValue!)
        } catch {
            fatalError("Couldn't parse \(linkname) as \(Cat.self):\n\(error)")
        }
    }
    task.resume()

    return
}


    var body : some View {

        List(cats, id: \.name) { cat in
            Text(cat.name)
        }.onAppear() {
            self.load("https://tmha-backend.herokuapp.com/api/cats/") { cats in
                self.cats = cats
            }

        }
    }
}


struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Chris
  • 7,579
  • 3
  • 18
  • 38