从公共 API 获取 JSON 以在 SwiftUI 的列表视图中呈现
Posted
技术标签:
【中文标题】从公共 API 获取 JSON 以在 SwiftUI 的列表视图中呈现【英文标题】:Getting JSON from a public API to render in a list view in SwiftUI 【发布时间】:2019-12-03 04:29:02 【问题描述】:我正在尝试从Rest Api
获取数据以下载并在SwiftUI
的列表视图中呈现。
我想我设法让JSON
正确下载并分配给所有相关的结构,但是当我去构建它时,模拟器的列表视图中没有显示任何内容。
我什至不确定是否需要在其中添加“Enum CodingKeys
”。
谁能指出我哪里出错了?
import Foundation
import SwiftUI
import Combine
struct ContentView: View
@ObservedObject var fetcher = LaunchDataFetcher()
var body: some View
VStack
List(fetcher.launches) launch in
VStack (alignment: .leading)
Text(launch.mission_name)
Text(launch.details)
.font(.system(size: 11))
.foregroundColor(Color.gray)
public class LaunchDataFetcher: ObservableObject
@Published var launches = [launch]()
init()
load()
func load()
let url = URL(string: "https://api.spacexdata.com/v3/launches")!
URLSession.shared.dataTask(with: url) (data,response,error) in
do
if let d = data
let decodedLists = try JSONDecoder().decode([launch].self, from: d)
DispatchQueue.main.async
self.launches = decodedLists
else
print("No Data")
catch
print ("Error")
.resume()
struct launch: Codable
public var flight_number: Int
public var mission_name: String
public var details: String
enum CodingKeys: String, CodingKey
case flight_number = "flight_number"
case mission_name = "mission_name"
case details = "details"
// Now conform to Identifiable
extension launch: Identifiable
var id: Int return flight_number
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
【问题讨论】:
如果键和结构成员具有相同的名称,则不需要 CodingKeys。如果您将结构成员命名为 camelCased 并添加convertFromSnakeCase
键解码策略,您甚至不需要 CodingKeys。
我以为是这样。感谢您的建议。
【参考方案1】:
首先,我尝试找出您的代码的哪个错误,并识别某处响应数据的launch.details为空。所以我只是将此属性标记为可选并且它可以工作。
更多细节,你可以参考下面的代码:
struct launch: Codable
public var flight_number: Int
public var mission_name: String
public var details: String?
enum CodingKeys: String, CodingKey
case flight_number = "flight_number"
case mission_name = "mission_name"
case details = "details"
在捕获线,获取错误消息以准确了解发生了什么
func load()
let url = URL(string: "https://api.spacexdata.com/v3/launches")!
URLSession.shared.dataTask(with: url) (data,response,error) in
do
if let d = data
let decodedLists = try JSONDecoder().decode([launch].self, from: d)
DispatchQueue.main.async
print(decodedLists)
self.launches = decodedLists
else
print("No Data")
catch let parsingError
print ("Error", parsingError)
.resume()
希望对您有所帮助!
【讨论】:
@Lofty 给我投票吧,这会让我更有动力^_^【参考方案2】:控制台中有任何消息吗?我认为您需要在 .plist 中添加 NSAppTransportSecurity>NSAllowsArbitraryLoads>YES
Transport security has blocked a cleartext HTTP
【讨论】:
我不需要这样做。【参考方案3】:在 Trai Nguyen 的帮助下,我设法让模拟器显示数据。
我所缺少的只是确保名为“详细信息”的变量具有可选属性(通过添加“?”) - 就像这样:
public var details: String?
然后确保当我在视图中呈现文本时,如果返回为空,我必须给它一个值以插入 - 就像这样:
Text(launch.details ?? "No Data Found")
这是适合我的完整代码:
import Foundation
import SwiftUI
import Combine
struct ContentView: View
@ObservedObject var fetcher = LaunchDataFetcher()
var body: some View
VStack
List(fetcher.launches) launch in
VStack (alignment: .leading)
Text(launch.mission_name)
Text(launch.details ?? "No Data Found")
.font(.system(size: 11))
.foregroundColor(Color.gray)
public class LaunchDataFetcher: ObservableObject
@Published var launches = [launch]()
init()
load()
func load()
let url = URL(string: "https://api.spacexdata.com/v3/launches")!
URLSession.shared.dataTask(with: url) (data,response,error) in
do
if let d = data
let decodedLists = try JSONDecoder().decode([launch].self, from: d)
DispatchQueue.main.async
print(decodedLists)
self.launches = decodedLists
else
print("No Data")
catch let parsingError
print ("Error", parsingError)
.resume()
struct launch: Codable
public var flight_number: Int
public var mission_name: String
public var details: String?
/// Now conform to Identifiable
extension launch: Identifiable
var id: Int return flight_number
struct ContentView_Previews: PreviewProvider
static var previews: some View
ContentView()
【讨论】:
以上是关于从公共 API 获取 JSON 以在 SwiftUI 的列表视图中呈现的主要内容,如果未能解决你的问题,请参考以下文章
Swift - 从模型中的 API 调用返回 JSON 对象作为字典以在视图控制器中使用
如何从 JSON 数组在 DB 中创建表以在 Spring Boot 中创建 REST API
如何准备 API 响应以在 swift 中与 jsonDecoder 一起使用
使用公共 API 从站点中提取 JSON 数据并将其异步显示在页面上