JSON API 在 Swift 中传输数据

JSON API transfer data in Swift

如何将数据从 json api 传递到 static func getAllStats()

我只需要从 JSON

传输 2 个参数 PW

struct Stat: Codable, Identifiable {
    
    var id = UUID()
    
    let image: String
    let name: String
    
    var p: String
    var w: String
    
    let t: String
}

extension Stat {

    static func getAllStats() -> [Stat] {

        return [

            Stat(image: "1", name: "Name1", p: "", w: "", t: "12"),

            Stat(image: "71", name: "Name2", p: "", w: "", t: "13"),

            Stat(image: "2", name: "Name3", p: "", w: "", t: "14")
        ]
    }
}

class Api {
    func getPost(completion: @escaping ([Stat]) -> ()) {
        
        guard let url = URL(string: "") else {return}
        
        URLSession.shared.dataTask(with: url) { (data, _, _) in
            
            let posts = try! JSONDecoder().decode([Stat].self, from: data!)
            
            DispatchQueue.main.async {
                completion(posts)
            }
        }
        .resume()
        
    }
}

我不清楚 什么标准 你将从 Stat 的数组中插入变量 pwStat 类型的其他对象中:它们是否需要匹配 ID?需要按顺序阅读吗?

我在下面建议的代码只为这 2 个变量创建了一个专用的 struct,我称之为 PW。这将避免将您在项目中使用的类型与从 API 下载的类型混淆。 PW 是将被解码的类型。

来自 api 的

pw 根据下载的 JSON 的顺序注入到 Stat 对象中,仅用于示例目的- 但是,这不是最佳做法,因此我建议相应地调整您的代码。

该示例使用 async 来避免完成处理程序和 DispatchQueue,但这不是必需的 - 只需使用您喜欢的方法即可。

// This is where the API will store the downloaded values
struct PW: Codable {
    let p: String?
    let w: String?
}

struct Stat: Codable, Identifiable {
    
    var id = UUID()
    
    let image: String
    let name: String

    // Replace 2 variables of type string with one variable of type PW
    var pw: PW
    
    let t: String
}

extension Stat {

    // This will allow the code to read p and w in a convenient way
    var p: String { pw.p ?? "" }
    var w: String { pw.w ?? "" }

    // async just to match the function in the Api class, but you
    // can use your own code
    static func getAllStats() async -> [Stat] {
        
        // Get the array of PW (with p and w values) from the api
        let pws = await Api().getPost()

        return [

            // Each object will store p and w values based on the order received:
            // this is NOT a best practice, a clear and unique criteria should be used
            Stat(image: "1",  name: "Name1", pw: pws[0], t: "12"),
            Stat(image: "71", name: "Name2", pw: pws[1], t: "13"),
            Stat(image: "2",  name: "Name3", pw: pws[2], t: "14")
        ]
    }
}

// This class is just for example purposes, implement your own code as you wish
class Api {
    
    // async just to avoid completion and DispatchQueue
    func getPost() async -> [PW] {
        
        guard let url = URL(string: "https://...") else { return [] }
        
        let request = URLRequest(url: url)
        
        do {
            let (data, response) = try await URLSession.shared.data(for: request)
            
            guard let httpResponse = response as? HTTPURLResponse,
                  (200...299).contains(httpResponse.statusCode) else {
                print("Error: HTTP response =\n\(response.debugDescription)")
                return []
            }
            
            // Decode type PW, not Stat
            let posts = try! JSONDecoder().decode([PW].self, from: data)
            return posts
        } catch {
            print("Oops: something went wrong!")
            return []
        }
    }
}

// Example of a view, just to show how to use the code
struct MyView: View {
    
    @State private var stats = [Stat]()

    var body: some View {
        VStack {
            ForEach(stats) { stat in
                VStack {
                    Text(stat.name)
                    Text(stat.p)
                    Text(stat.w)
                }
            }
        }
        .task {
            stats = await Stat.getAllStats()
        }
    }
}