我正在制作一個需要從兩個 API(
每次發射都有一個與第一個 API 中四個火箭之一的 ID 相匹配的 ID。在我的應用程式中,有四個選項卡,其中包含有關每個火箭的資訊和一個通向另一個視圖的按鈕,其中應顯示有關該火箭的所有發射的資訊(名稱、日期以及發射是否成功)。
- 我不知道如何更新我的模型,以便我可以一次決議來自兩個 API 的資訊。
- 我也無法弄清楚如何在單獨的視圖上顯示有關特定火箭的所有發射的資訊,首先檢查它們的 ID 是否與第一個 API 中的特定火箭 ID 匹配。
uj5u.com熱心網友回復:
編輯-1:
最好的辦法是重構你的代碼并使用 a
ObservableObject class來完成所有的獲取、處理和發布。
這是一些使用ObservableObject類的示例代碼。
struct ContentView: View {
@StateObject var spacex = SpacexModel() // <-- here
var body: some View {
NavigationView {
if spacex.loadingRockets || spacex.loadingLaunches { // <-- here
ProgressView()
} else {
TabView {
ForEach(spacex.rockets) { rocket in // <-- here
ScrollView(.vertical, showsIndicators: false) {
VStack {
//MARK: - HEADER IMAGE
Image(systemName: "globe") // <-- for testing
.renderingMode(.original)
.resizable()
.scaledToFill()
.frame(width: 190, height: 190, alignment: .center)
.padding(.bottom, 32)
//MARK: - INFO
VStack(spacing: 40) {
HStack {
Text(rocket.name).font(.title)
Spacer()
}
HStack {
Text("First flight")
Spacer()
Text(rocket.first_flight)
}
HStack {
Text("Country")
Spacer()
Text(rocket.country)
}
HStack {
Text("Cost per launch")
Spacer()
Text("$\(rocket.cost_per_launch / 1000000)M")
}
} //: VSTACK
.padding(.horizontal, 32)
//MARK: - LAUNCHES BUTTON
NavigationLink {
LaunchDetailView(rocket: rocket) // <-- here
} label: {
Text("Launches".uppercased())
.font(.headline)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 56, maxHeight: 56, alignment: .center)
.background(
Color(UIColor.secondarySystemFill)
.clipShape(RoundedRectangle(cornerRadius: 12, style: .continuous))
)
.foregroundColor(Color.green)
.padding(32)
}
} //: VSTACK
} //: SCROLL
} //: LOOP
} //: TAB
.tabViewStyle(.page)
.navigationBarTitleDisplayMode(.inline)
.navigationBarHidden(true)
.edgesIgnoringSafeArea(.vertical)
}
} //: NAVIGATION
.navigationViewStyle(.stack)
.environmentObject(spacex) // <-- here
.edgesIgnoringSafeArea(.vertical)
}
}
struct LaunchDetailView: View {
@EnvironmentObject var spacex: SpacexModel // <-- here
let rocket: RocketInfo // <-- here
var body: some View {
VStack {
Text("launches for \(rocket.name)").foregroundColor(.blue)
List {
ForEach(spacex.launchesFor(rocket)) { launch in
VStack {
Text(launch.name).foregroundColor(.green)
Text("launch \(launch.details ?? "no details")")
}
}
}
}
}
}
class SpacexModel: ObservableObject {
@Published var rockets = [RocketInfo]()
@Published var launches = [LaunchInfo]()
@Published var loadingRockets = false
@Published var loadingLaunches = false
init() {
getRockets()
getLaunches()
}
func getRockets() {
self.loadingRockets = true
guard let url = URL(string: "https://api.spacexdata.com/v4/rockets") else {
return
}
URLSession.shared.dataTask(with: url) { (data, response, error) in
// todo deal with errors
guard let data = data, error == nil else { return }
DispatchQueue.main.async {
do {
self.rockets = try JSONDecoder().decode([RocketInfo].self, from: data)
self.loadingRockets = false
} catch {
print(error)
}
}
}.resume()
}
func getLaunches() {
self.loadingLaunches = true
guard let url = URL(string: "https://api.spacexdata.com/v4/launches") else {
return
}
URLSession.shared.dataTask(with: url) { (data, response, error) in
// todo deal with errors
guard let data = data, error == nil else { return }
DispatchQueue.main.async {
do {
self.launches = try JSONDecoder().decode([LaunchInfo].self, from: data)
self.loadingLaunches = false
} catch {
print(error)
}
}
}.resume()
}
func launchesFor(_ rocket: RocketInfo) -> [LaunchInfo] {
return launches.filter{ $0.rocket == rocket.id }
}
}
struct RocketInfo: Codable, Identifiable {
let id: String // <-- here
let name: String
let country: String
let first_flight: String
let cost_per_launch: Int
// ...
}
struct LaunchInfo: Identifiable, Codable {
let id: String
let rocket: String // <-- here
let details: String?
let crew, ships, capsules, payloads: [String]
let name: String
// ...
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/461364.html
上一篇:從CSV到Java中的XML
