Search code examples
swiftswiftuipagetabviewstyle

Getting the out of range index error when trying to make a Page Tab View from API array


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()
    }
}

Solution

  • 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
                }
            }
        }
    }