从 public API 获取 JSON 以在 SwiftUI 的列表视图中呈现
Getting JSON from a public API to render in a list view in SwiftUI
我正在尝试从 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()
}
}
首先,我尝试找出您的代码的哪个错误,并识别某处响应数据的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"
}
}
在 catch 行,获取错误消息以确切了解发生了什么
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()
}
希望对您有所帮助!
控制台中有任何消息吗?我认为您需要在 .plist
中添加 NSAppTransportSecurity>NSAllowsArbitraryLoads>YES
在Trai Nguyen的帮助下,我设法让模拟器显示数据。
我所缺少的只是确保名为 'details' 的变量有一个可选的 属性(通过添加“?”)——像这样:
public var details: String?
然后确保当我在我的视图中呈现文本时,如果 return 为空,我必须给它一个要插入的值 - 就像这样:
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()
}
}
我正在尝试从 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()
}
}
首先,我尝试找出您的代码的哪个错误,并识别某处响应数据的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"
}
}
在 catch 行,获取错误消息以确切了解发生了什么
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()
}
希望对您有所帮助!
控制台中有任何消息吗?我认为您需要在 .plist
中添加 NSAppTransportSecurity>NSAllowsArbitraryLoads>YES在Trai Nguyen的帮助下,我设法让模拟器显示数据。
我所缺少的只是确保名为 'details' 的变量有一个可选的 属性(通过添加“?”)——像这样:
public var details: String?
然后确保当我在我的视图中呈现文本时,如果 return 为空,我必须给它一个要插入的值 - 就像这样:
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()
}
}