如何完全删除 NavigationView 中的 Navbar
How to delete Navbar in NavigationView at all
我已经 当我从 API 获取数据时,如何在使用 页面样式 TabView 时摆脱超出范围的索引错误.有人建议我这样做:
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()
}
}
它有所帮助,但还有另一个问题。要将 TabView 包装在 if-else 子句中,我必须在其外部添加一些其他视图(例如,NavigationView)并调用 onAppear 这个视图的方法使一切正常。问题是我无法完全删除 NavigationView.
顶部的白色安全区域
That's what it looks like in the Simulator
如果我将 TabView 包装在 HStack 而不是 NavigationView 中,然后将 ScrollView 滚动到最后看到最底下有个白条,也不知道怎么去掉。
This white space at the bottom of the ScrollView I was talking about
对此有许多可能的解决方案。所有这些都涉及摆脱 NavigationView
,因为看起来您唯一的用途就是需要某种包装视图。
解决方案 #1:
将您的 isEmpty
支票移到 TabView
内
var body: some View {
TabView {
if rockets.isEmpty {
//ProgressView
} else {
//your tabs
}
}.onAppear {
//API call
}
}
解决方案#2:
将您的内容包装在 Group
:
中,而不是 NavigationView
var body: some View {
Group {
if !rockets.isEmpty {
TabView { /*...*/ }
}
}.onAppear {
//API call
}
}
解决方案 #3:在进度视图出现时调用 onAppear
if rockets.isEmpty {
ProgressView()
.onAppear {
//API call
}
} else {
TabView {
//tab content
}
}
编辑:带有模拟的完整示例 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
}
}
}
}
不幸的是,事实证明,如果在一个视图中同时使用 TabBar 和 NavigationView,则完全不可能摆脱导航栏。
我已经
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()
}
}
它有所帮助,但还有另一个问题。要将 TabView 包装在 if-else 子句中,我必须在其外部添加一些其他视图(例如,NavigationView)并调用 onAppear 这个视图的方法使一切正常。问题是我无法完全删除 NavigationView.
顶部的白色安全区域That's what it looks like in the Simulator
如果我将 TabView 包装在 HStack 而不是 NavigationView 中,然后将 ScrollView 滚动到最后看到最底下有个白条,也不知道怎么去掉。
This white space at the bottom of the ScrollView I was talking about
对此有许多可能的解决方案。所有这些都涉及摆脱 NavigationView
,因为看起来您唯一的用途就是需要某种包装视图。
解决方案 #1:
将您的 isEmpty
支票移到 TabView
var body: some View {
TabView {
if rockets.isEmpty {
//ProgressView
} else {
//your tabs
}
}.onAppear {
//API call
}
}
解决方案#2:
将您的内容包装在 Group
:
NavigationView
var body: some View {
Group {
if !rockets.isEmpty {
TabView { /*...*/ }
}
}.onAppear {
//API call
}
}
解决方案 #3:在进度视图出现时调用 onAppear
if rockets.isEmpty {
ProgressView()
.onAppear {
//API call
}
} else {
TabView {
//tab content
}
}
编辑:带有模拟的完整示例 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
}
}
}
}
不幸的是,事实证明,如果在一个视图中同时使用 TabBar 和 NavigationView,则完全不可能摆脱导航栏。