【问题标题】:What did I do wrong here when working with an API?使用 API 时我在这里做错了什么?
【发布时间】:2020-06-06 19:44:52
【问题描述】:

首先:我是 Swift 和 SwiftUI 的初学者。我将不胜感激任何帮助,即使它与我的问题无关! 现在我的问题: 为了练习 SwiftUI 和 API,我想构建一个小应用程序来显示有关冠状病毒的一些数据,非常简单。这是我使用的 API:Coronavirus API。 现在这是我的代码:

import SwiftUI

struct GlobalResult: Decodable {
    var cases: Int
    var deaths: Int
    var recovered: Int
}

struct Statistics : View {
    @State var global: GlobalResult!

    var body: some View {
         VStack {
              VStack {
                Text("\(self.global.cases)")
              }
         }.onAppear() {
               ApiShared.shared.getData()
         }
     }
}



class Api {
    @Published var data: GlobalResult!

func getData() {
    let url = "https://corona.lmao.ninja/v2/all"

    let session = URLSession(configuration: .default)

    session.dataTask(with: URL(string: url)!) { (data, _, err) in

        if err != nil {

            print((err?.localizedDescription)!)
            return
        }

        let json = try! JSONDecoder().decode(GlobalResult.self, from: data!)

        DispatchQueue.main.async {
            self.data = json
        }
    }
    .resume()
}
}

class ApiShared {
    static let shared = Api()
}

struct Statistics_Previews: PreviewProvider {
    static var previews: some View {
        Statistics()
    }
}

但它不起作用!我遵循了一些关于 YT 的教程,并且可以使其正常工作。有人可以帮我吗? 当我删除 if 语句 它说“致命错误:在隐式展开可选值时意外发现 nil” 非常感谢!

【问题讨论】:

  • if 语句中显示的localizedDescription 是什么?
  • tbh,我真的不知道,它来自教程。但我认为那是错误
  • 几件事:避免使用! 来强制包装可选值。而不是 print((err?.localizedDescription)!) 做 print((err?.localizedDescription) ?? "")。这应该可以帮助您进一步调试以及发生了什么。
  • data! 相同。我没有意识到你在两个不同的地方大获全胜。无论发生 fata 错误,您都希望它优雅地失败,以便您可以继续调试您的问题
  • 我应该如何处理“!”?

标签: ios json swift api swiftui


【解决方案1】:

我从未使用过 SwiftUI,但在我看来问题出在其中。与您的 var 数据有关的内容。 我稍微改变了你的功能。

func getData() {
    let url = "https://corona.lmao.ninja/v2/all"
    let session = URLSession(configuration: .default)
    session.dataTask(with: URL(string: url)!) { (data, responce, err) in
        if let error = err {

            print(error.localizedDescription)
            return
        }
        if let responce = responce{
            print(responce)
        }

        if let data = data{
            do {
                let json = try JSONDecoder().decode(GlobalResult.self, from: data)
                print(json)
            } catch{
                print(error.localizedDescription)
            }
        }
    }
    .resume()
}

得到了结果。尝试以相同的方式更改函数,您将在控制台中看到打印的响应,这意味着 var 数据确实存在问题。

【讨论】:

  • 是的,你说得对!我在控制台中看到它。现在我必须弄清楚如何显示它。
  • 您找到解决问题的方法了吗?
【解决方案2】:

上一个答案提供了一种安全获取数据而不会崩溃的好方法,但是您仍然没有将 getData() 函数的结果设置为视图中的全局变量。尝试更改您的 getData() 函数以返回如下所示的 GlobalResult 对象:

func getData() -> GlobalResult? {
     let url = "https://corona.lmao.ninja/v2/all"
     let session = URLSession(configuration: .default)
     session.dataTask(with: URL(string: url)!) { (data, responce, err) in
         if let error = err {
             print(error.localizedDescription)
             return nil
         }
         if let responce = responce{
             print(responce)
         }

         if let data = data{
             do {
                 let json = try JSONDecoder().decode(GlobalResult.self, from: data)
                 print(json)
                 return json
             } catch{
                 print(error.localizedDescription)
                return nil
             }
         }
     }
     .resume()
 }

如果成功则返回 GlobalResult 值,否则返回 nil。然后在您的统计视图中,您可以执行以下操作:

struct Statistics : View {
@State var global: GlobalResult!

var body: some View {
     VStack {
          VStack {
            Text("\(self.global.cases)")
          }
     }.onAppear() {
           let result = ApiShared.shared.getData()
           if result != nil {
               global = result
           }
     }
     }
 }

这将获取 getData() 调用的结果,如果不为零,则将其设置为全局变量。我认为您不需要 Api 类中的 @Published 变量。

【讨论】:

  • 感谢您的回答,但是当我输入“return nil”或“return json”时,它会显示“在 void 函数中出现意外的非 void 返回值”
  • 确保您的 getData() 函数定义被编写为返回 GlobalResult?类型。请参阅我的第一个代码 sn-p 的顶部。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-06
  • 1970-01-01
  • 2016-03-03
  • 2013-06-28
  • 2023-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多