I've already asked here how to get rid of an out of range index error when using page styled TabView when I get data from API. There I was advised to do this:
Add an if rockets.isEmpty clause around the entire TabView and display something else if the array is empty (like a loading indicator)
// 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
}
// MARK: - CONTENT VIEW
struct ContentView: View {
@State var rockets: [RocketInfo] = []
var body: some View {
Group {
if rockets.isEmpty {
ProgressView()
} else {
NavigationView {
TabView {
ForEach(rockets) { rocket in
ScrollView(.vertical, showsIndicators: false) {
VStack(alignment: .center) {
Image(systemName: "globe")
.renderingMode(.original)
.resizable()
.scaledToFit()
.frame(height: 190, alignment: .center)
ZStack {
RoundedRectangle(cornerRadius: 32)
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 865, maxHeight: .infinity, alignment: .center)
.foregroundColor(Color.gray)
VStack(spacing: 40) {
HStack {
Text("Name")
.font(.title)
Spacer()
Text(rocket.name)
.font(.title)
}
} //: VSTACK
.padding(.horizontal)
} //: ZSTACK
} //: VSTACK
.navigationBarTitleDisplayMode(.inline)
.navigationBarHidden(true)
} //: SCROLL
} //: LOOP
} //: TAB
.tabViewStyle(.page)
.edgesIgnoringSafeArea(.vertical)
} //: NAVIGATION
}
} //: GROUP
.onAppear {
InfoApi().getRockets { rockets in
self.rockets = rockets
}
}
.edgesIgnoringSafeArea(.vertical)
}
}
// MARK: - PREVIEW
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
It helped, but there was another problem. To wrap TabView in an if-else clause, I had to add some other View outside it (for example, NavigationView) and call the onAppear method for this View to make everything work. There was a problem with the fact that I cannot completely remove the white safe area at the top of NavigationView.
That's what it looks like in the Simulator
If I wrap TabView in HStack instead of NavigationView, then when scrolling ScrollView to the end, I see a white bar at the very bottom, which I also don't know how to get rid of.
This white space at the bottom of the ScrollView I was talking about
Unfortunately, it turned out that it is quite impossible to get rid of navbar if you use both TabBar and NavigationView in one View.