This is my Model:
class Api {
func getRockets(completion: @escaping ([Rocket]) -> ()) {
guard let url = URL(string: "https://api.spacexdata.com/v4/rockets") else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
do {
let rockets = try JSONDecoder().decode([Rocket].self, from: data!)
DispatchQueue.main.async {
completion(rockets)
}
} catch {
print(error.localizedDescription)
}
}
.resume()
}
}
I try to make PageTabView using elements from the API array, but my app crashes with an out of range index error.
This is the View that doesn't work properly:
struct TestTabViewView: View {
@State var rockets: [Rocket] = [] //<-- The array of items from the API I use to make tabs
var body: some View {
TabView {
ForEach(rockets) { rocket in
Text(rocket.name)
}
}
.onAppear {
Api().getRockets { rockets in
self.rockets = rockets
}
}
.tabViewStyle(.page)
}
}
struct TestTabViewView_Previews: PreviewProvider {
static var previews: some View {
TestTabViewView()
}
}
If you put TabView
inside an if-else statement, and in turn put this statement inside NavigationView
or Group
, and then call the .onAppear
method for an external container (for example, Group
), everything will work properly and there will be no an out of range index error.
struct TestTabViewView: View {
@State var rockets: [Rocket] = []
var body: some View {
Group {
if rockets.isEmpty {
ProgressView()
} else {
TabView {
ForEach(rockets) { rocket in
Text(rocket.name)
}
}
.tabViewStyle(.page)
}
}
.onAppear {
Api().getRockets { rockets in
self.rockets = rockets
}
}
}
}