Как разобрать json url api в массив глобальных переменных в Swift 5 - PullRequest
0 голосов
/ 09 мая 2020

(см. Ниже) Этот код изначально был реализован с помощью текстового файла. json, но теперь я пытаюсь изменить его, чтобы реализовать с живым URL-адресом, и я не уверен, как сделать его глобальной переменной, поскольку однажды вы переключаетесь на URL-адрес, у него есть задача URLSession, и вам нужно использовать task.resume (), чтобы он продолжал обновляться, но тогда я не уверен, как я смогу вернуть декодируемый T в массив catData как функцию void . Пожалуйста, помогите Спасибо!

Начало моей новой реализации:

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()
}

исходный код:

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)")
    }
}

1 Ответ

0 голосов
/ 09 мая 2020

попробуйте следующее: (решение с блоком завершения, которое вы должны использовать, если вы загружаете что-то asyn c в функцию)

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()
    }
}
...