这个 API 对 SwiftUI 的调用有什么问题

What is wrong with this API call for SwiftUI

我一直在尝试使用 swiftui 进行 API 调用,但是当我 运行代码。这是当前程序:

import SwiftUI


struct Post: Codable, Identifiable {
    var id = UUID()
    var title: String
    var body: String
}

class Api {
    func getPosts(){
        guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else { return}
        URLSession.shared.dataTask(with: url) { data, _, _ in
            let posts = try! JSONDecoder().decode([Post].self, from: data!)
            print(posts)
        }
        .resume()
    }
}

// Content view file
import SwiftUI

struct PostList: View {
    var body: some View {
        Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/)
            .onAppear{
                Api().getPosts()
            }
    }
}

struct PostList_Previews: PreviewProvider {
    static var previews: some View {
        PostList()
    }
}

我从 swift 教程中逐字获取了这段代码,但我从中得到了错误。任何帮助将不胜感激!

问题的发生是因为这一行:

let posts = try! JSONDecoder().decode([Post].self, from: data!)

你正在强制展开尝试!并且 swift 无法将您的数据解码为 [Post] 因为您的模型是错误的,为此进行更改:

struct Post: Codable {
var userId: Int
var id: Int
var title: String
var body: String
}

您的应用程序将会编译,请避免使用强制解包。

要“修复”您的错误,请在您的 Post 模型中使用 var id: Int。 还可以使用以下代码,它比您一直使用的教程代码更可靠:请参阅此 SO post: Preview Crashed when I get data from api

struct ContentView: View {
    @State var posts: [Post] = []

    var body: some View {
        VStack {
            List(posts) { post in
                Text(post.title)
            }
            .onAppear{
                Api.shared.getPosts { posts in  // <-- here
                    self.posts = posts
                }
            }
        }
    }
}

struct Post: Codable, Identifiable {
    var id: Int  // <-- here
    var title: String
    var body: String
}

class Api {
    
    static let shared = Api()  // <-- here
    
    func getPosts(completion: @escaping([Post]) -> ()) {
        guard let url = URL(string: "https://jsonplaceholder.typicode.com/posts") else { return
            print("bad url")
        }
        
        URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data else {   // <-- here
                print("no data") // todo deal with no data
                completion([])
                return
            }
            do {
                let posts = try JSONDecoder().decode([Post].self, from: data)
                DispatchQueue.main.async {
                    completion(posts)
                }
                print(posts)
            } catch {
                print("\(error)")
            }
        }
        .resume()
    }
}