如何解析两个API的数据
我正在制作一个应用程序,其中我需要从两个API( first 和 second )。我想出了如何从第一个API获取数据,但是第二个API有问题。我与第一个API合作,如下所示。
对于第一个API,我使用此模型,然后在视图中创建@State属性,在Body()中,我将通过DOT语法称为所需的变量。
// MARK: - API
class InfoApi {
func getRockets(completion: @escaping ([RocketInfo]) -> ()) {
guard let url = URL(string: "https://api.spacexdata.com/v4/rockets") else {
return
}
URLSession.shared.dataTask(with: url) { (data, response, error) in
do {
let rocketsInfo = try JSONDecoder().decode([RocketInfo].self, from: data!)
DispatchQueue.main.async {
completion(rocketsInfo)
}
} catch {
print(error.localizedDescription)
}
}
.resume()
}
}
// MARK: - ROCKET MODEL
struct RocketInfo: Codable, Identifiable {
let id = UUID()
let name: String
let country: String
let first_flight: String
let cost_per_launch: Int
}
// MARK: - CONTENT VIEW
struct ContentView: View {
@State var rockets: [RocketInfo] = []
var body: some View {
NavigationView {
if rockets.isEmpty {
ProgressView()
} else {
TabView {
ForEach(rockets) { rocket in
ScrollView(.vertical, showsIndicators: false) {
VStack {
//MARK: - HEADER IMAGE
Image("Image2")
.renderingMode(.original)
.resizable()
.scaledToFill()
.frame(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()
} 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
.onAppear {
InfoApi().getRockets { rockets in
self.rockets = rockets
}
}
.edgesIgnoringSafeArea(.vertical)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.preferredColorScheme(.dark)
}
}
第二个API的问题在于它包含了第一个API中所有四个火箭的启动列表,并且这些启动中的每一个都有一个单独的ID,该ID与第一个API中的四个火箭之一的ID匹配。
在简称中,首先API 包含 4火箭的列表和每个参数,以及 second api 包含所有发射的列表。 Note :我浏览了第二个API,发现四个火箭中的一台根本没有发射,另一个火箭的发射时间多达160。老实说,我什至不能只是解析从第二个API开始的整个启动列表,使用与第一个API相同的模型,但更改了该API本身的链接。
每个启动都有一个ID,该ID与第一个API中四个火箭之一的ID匹配。在我的应用程序中,有四个选项卡,其中包含有关每种火箭的信息和一个按钮,可导致另一个视图,其中应显示有关此火箭的所有启动(名称,日期和是否成功的发布)的信息。
- 我不知道如何更新我的模型,以便可以一次从两个API中解析信息。
- 我也无法弄清楚如何在单独的视图上显示有关特定火箭的所有启动的信息,因为首先检查了它们的ID是否与第一个API的特定火箭ID匹配。
I'm making an app where I need to parse data from two APIs (first and second). I figured out how to get data from the first API, but there was a problem with the second one. I work with the first API as follows.
For the first API, I use this model, then in the View I create the @State property and in the Body() I call the variables I need through dot syntax.
// MARK: - API
class InfoApi {
func getRockets(completion: @escaping ([RocketInfo]) -> ()) {
guard let url = URL(string: "https://api.spacexdata.com/v4/rockets") else {
return
}
URLSession.shared.dataTask(with: url) { (data, response, error) in
do {
let rocketsInfo = try JSONDecoder().decode([RocketInfo].self, from: data!)
DispatchQueue.main.async {
completion(rocketsInfo)
}
} catch {
print(error.localizedDescription)
}
}
.resume()
}
}
// MARK: - ROCKET MODEL
struct RocketInfo: Codable, Identifiable {
let id = UUID()
let name: String
let country: String
let first_flight: String
let cost_per_launch: Int
}
// MARK: - CONTENT VIEW
struct ContentView: View {
@State var rockets: [RocketInfo] = []
var body: some View {
NavigationView {
if rockets.isEmpty {
ProgressView()
} else {
TabView {
ForEach(rockets) { rocket in
ScrollView(.vertical, showsIndicators: false) {
VStack {
//MARK: - HEADER IMAGE
Image("Image2")
.renderingMode(.original)
.resizable()
.scaledToFill()
.frame(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()
} 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
.onAppear {
InfoApi().getRockets { rockets in
self.rockets = rockets
}
}
.edgesIgnoringSafeArea(.vertical)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.preferredColorScheme(.dark)
}
}
The problem with the second API is that it contains a list of launches of all four rockets that are in the first API, and each of these launches has an individual ID that matches the ID of one of the four rockets from the first API.
In short, the first API contains a list of 4 rockets and the parameters of each of them, and the second API contains a list of all launches of these rockets.
Note: I looked through the second API and found that one of the four rockets had no launches at all, and the other one had as many as 160. To be honest, I can't even just parse the entire list of launches from the second API, using the same model as for the first API, but changing the link to this API itself.
Each launch has an ID that matches the ID of one of the four rockets in the first API. In my application there are four tabs with information about each rocket and a button that leads to another View where information about all the launches of this rocket (name, date and whether the launch was successful) should be displayed.
- I do not know how to update my model so that I can parse information from two APIs at once.
- I also can't figure out how I can display information about all launches of a particular rocket on a separate View, having first checked that their IDs match to particular rocket ID from the first API.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Edit-1:
最好的事情是重组您的代码并使用
可观察到的类别类
进行所有获取,处理和发布。这是一些使用
observableObject
类的示例代码。EDIT-1:
The best thing to do, is to restructure your code and use a
ObservableObject class
to do all fetching, processing and publishing.Here is some example code using an
ObservableObject
class.