使用 API 时我在这里做错了啥?
Posted
技术标签:
【中文标题】使用 API 时我在这里做错了啥?【英文标题】: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 错误,您都希望它优雅地失败,以便您可以继续调试您的问题
我应该如何处理“!”?
【参考方案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 的顶部。以上是关于使用 API 时我在这里做错了啥?的主要内容,如果未能解决你的问题,请参考以下文章