如何在我的 SwiftUI 应用程序中显示来自 Api 的数据

时间:2021-07-20 16:50:27

标签: json api swiftui

我正在制作这个应用程序,它会显示有关即将上映的动漫的某些信息,为此我使用了 jikan API,它不需要任何身份验证或任何密钥

API 的外观 -

{
  "request_hash": "request:top:3506eaba6445f7ad5cc2f78417bf6ed916b6aaad",
  "request_cached": true,
  "request_cache_expiry": 43675,
  "top": [
    {
      "mal_id": 40356,
      "rank": 1,
      "title": "Tate no Yuusha no Nariagari Season 2",
      "url": "https://myanimelist.net/anime/40356/Tate_no_Yuusha_no_Nariagari_Season_2",
      "image_url": "https://cdn.myanimelist.net/images/anime/1245/111800.jpg?s=7302aaeb3bc4e1433b32d094e9d6f6f0",
      "type": "TV",
      "episodes": {},
      "start_date": "Apr 2022",
      "end_date": {},
      "members": 300837,
      "score": 0
    },
    {
      "mal_id": 48583,
      "rank": 2,
      "title": "Shingeki no Kyojin: The Final Season Part 2",
      "url": "https://myanimelist.net/anime/48583/Shingeki_no_Kyojin__The_Final_Season_Part_2",
      "image_url": "https://cdn.myanimelist.net/images/anime/1989/116577.jpg?s=f6312bda2e67f86595936d0264696a91",
      "type": "TV",
      "episodes": {},
      "start_date": "Jan 2022",
      "end_date": {},
      "members": 253849,
      "score": 0
    },

这就是我编写代码的方式,出于某种原因,当我运行该应用程序时,我只是得到一个纯空白屏幕,并且它还会打印出我添加的最后一条打印语句,上面写着“获取失败:未知错误” 请帮我解决这个问题

 import SwiftUI


struct Response: Codable{
    var top: [Result]
    
}

struct Result: Codable {
    
    var mal_id: Int
    var rank: Int
    var title: String
    var type: String
    var start_date: String
    
}

struct ContentView: View {
    
    func loadData() {

        guard let url = URL(string: "https://api.jikan.moe/v3/top/anime/1/upcoming") else {
            print("Invalid URL")
            return
        }
        
        let request = URLRequest(url: url)
        
        URLSession.shared.dataTask(with: request) { data, response, error in
            if let data = data {
                if let decodedResponse = try? JSONDecoder().decode(Response.self, from: data) {
                    // we have good data – go back to the main thread
                    DispatchQueue.main.async {
                        // update our UI
                        self.top = decodedResponse.top
                    }

                    // everything is good, so we can exit
                    return
                }
            }

            // if we're still here it means there was a problem
            print("Fetch failed: \(error?.localizedDescription ?? "Unknown error")")
        }.resume()
    }
    
    @State private var top = [Result]()
    var body: some View {
        ScrollView {
            List(top, id: \.mal_id) { item in
                        VStack(alignment: .leading) {
                            Text(item.title)
                                .font(.headline)
                            Text(String("\(item.rank)"))
                                .font(.headline)
                            Text(item.type)
                                .font(.headline)
                            Text(item.start_date)
                                .font(.headline)
                            
                        }
                    }
                       }
           
        .onAppear(perform: loadData)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

1 个答案:

答案 0 :(得分:0)

首先,在解码你的数据时遇到问题,看起来有些字段是作为null来的,所以你应该将它们解码为可选的,在这种情况下我发现var start_date: String字段是导致问题的一个,因此请确保将其设为可选:var start_date: String?

其次,您不需要将 List 放在 ScrollView 中,因为默认情况下 ListScrollView 的类型。

模型:(使一些文件可选)

struct Result: Codable {
    var mal_id: Int
    var rank: Int
    var title: String
    var type: String
    var start_date: String?
}

正文内容:(移除了滚动视图)

var body: some View {
    List(top, id: \.mal_id) { item in
        VStack(alignment: .leading) {
            Text(item.title)
                .font(.headline)
            Text(String("\(item.rank)"))
                .font(.headline)
            Text(item.type)
                .font(.headline)
            Text(item.start_date ?? "")
                .font(.headline)
            
        }
    }
    .onAppear(perform: loadData)
}