bowtie
bowtie

Reputation: 31

How to delete Navbar in NavigationView at all

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

The View that I want to create

Upvotes: 0

Views: 100

Answers (2)

bowtie
bowtie

Reputation: 31

Unfortunately, it turned out that it is quite impossible to get rid of navbar if you use both TabBar and NavigationView in one View.

Upvotes: 0

jnpdx
jnpdx

Reputation: 52387

There are a number of potential solutions to this. All involve getting rid of the NavigationView since it seems that your only use for it was that you needed some sort of wrapper view.

Solution #1: Move your isEmpty check inside the TabView

var body: some View {
  TabView {
    if rockets.isEmpty {
      //ProgressView
    } else {
      //your tabs
    }
  }.onAppear {
    //API call
  }
}

Solution #2: Instead of NavigationView, wrap your content in a Group:

var body: some View {
  Group {
    if !rockets.isEmpty {
      TabView { /*...*/ }
    }
  }.onAppear {
    //API call
  }
}

Solution #3: call onAppear on the progress view when it appears

if rockets.isEmpty {
  ProgressView()
   .onAppear {
     //API call
   }
} else {
  TabView {
    //tab content
  }
}

Edit: complete example with mocked objects/API

struct TabBarView: View {
    @State var rockets: [RocketInfo] = []
    
    var body: some View {
        Group {
            if rockets.isEmpty {
                ProgressView()
            } else {
                NavigationView {
                    TabView {
                        
                        ForEach(rockets) { rocket in
                            Text(rocket.title)
                        }
                        
                    }
                    .tabViewStyle(.page)
                }
            }
        }
        .onAppear {
            InfoApi().getRockets { rockets in
                self.rockets = rockets
            }
        }
    }
}

Upvotes: 1

Related Questions