5

看起来 Navigation + TabView + Sheet 在 iOS 15 中被破坏了。

当我这样做时: ContentView -> DetailView -> Bottom Sheet

当底部工作表出现时,Detail视图会自动从堆栈中弹出: https ://www.youtube.com/watch?v=gguLptAx0l4

我希望Detail即使出现底部表格,视图也会保留在那里。有谁知道为什么会发生这种情况以及如何解决它?

这是我的示例代码:

import Combine
import SwiftUI
import RealmSwift

struct ContentView: View {

    var body: some View {
        NavigationView {
            TabView {
                TabItemView(num: 1)
                    .tabItem {
                        Text("One")
                    }
                TabItemView(num: 2)
                    .tabItem {
                        Text("Two")
                    }
            }
        }
    }
}

struct TabItemView: View {

    private let num: Int

    init(num: Int) {
        self.num = num
    }

    var body: some View {
        NavigationLink(destination: DetailView(text: "Detail View \(num)")) {
            Text("Go to Detail View")
        }
    }
}

struct DetailView: View {

    @State private var showingSheet = false

    private let text: String

    init(text: String) {
        self.text = text
    }

    var body: some View {
        Button("Open Sheet") {
            showingSheet.toggle()
        }.sheet(isPresented: $showingSheet) {
            Text("Sheet Text")
        }
    }
}

这适用于 iOS 14 顺便说一句

更新 1:

尝试了@Sebastian 提出的NavigationViewTabView. 虽然这修复了导航错误,但它从根本上改变了行为(我不想在 中显示选项卡DetailView)。

还尝试了他使用Introspect设置目的地navigationController.hidesBottomBarWhenPushed = true的建议NavigationLink,但这并没有做任何事情:

struct ContentView: View {
    
    var body: some View {
        TabView {
            NavigationView {
                TabItemView(num: 1)
            }.tabItem {
                Text("One")
            }
            NavigationView {
                TabItemView(num: 2)
            }.tabItem {
                Text("Two")
            }
        }
    }
}

struct TabItemView: View {
    
    private let num: Int
    
    init(num: Int) {
        self.num = num
    }
    
    var body: some View {
        NavigationLink(destination: DetailView(text: "Detail View \(num)").introspectNavigationController { navigationController in
            navigationController.hidesBottomBarWhenPushed = true
        }) {
            Text("Go to Detail View")
        }
    }
}

struct DetailView: View {
    
    @State private var showingSheet = false
    
    private let text: String
    
    init(text: String) {
        self.text = text
    }
    
    var body: some View {
        Button("Open Sheet") {
            showingSheet.toggle()
        }.sheet(isPresented: $showingSheet) {
            Text("Sheet Text")
        }
    }
}
4

1 回答 1

1

您需要翻转嵌套TabView&的方式NavigationView。与其在 a 中嵌套多个TabView视图NavigationViewTabView不如将 用作父组件,NavigationView每个选项卡都有一个。

这是更新后的ContentView样子:

struct ContentView: View {
    var body: some View {
        TabView {
            NavigationView {
                TabItemView(num: 1)
            }
            .tabItem {
                Text("One")
            }
            
            NavigationView {
                TabItemView(num: 2)
            }
            .tabItem {
                Text("Two")
            }
        }
    }
}

这是有道理的,而且更正确:选项卡应该始终可见,但您希望在每个选项卡中显示具有不同内容的不同导航堆栈。

它之前的工作并没有使它更正确 - SwiftUI 可能只是改变了处理意外情况的想法。那个,以及在这些情况下缺少错误消息,是使用一个试图渲染你扔给它的任何东西的框架的缺点!


如果目标是在 NavigationView 上推送新视图时(例如,在消息应用程序中点击对话时)隐藏选项卡,则必须使用不同的解决方案。Apple 将该UIViewController.hidesBottomBarWhenPushed属性添加到 UIKit 以支持此特定用例。

此属性设置在 UIViewController 上,当它出现时,不应显示工具栏。换句话说:不是 UINavigationController 或 UITabBarController,而是您推送到 UINavigationController 上的子 UIViewController。

SwiftUI 本身不支持此属性。您可以使用SwiftUI-Introspect设置它,或者简单地使用 UIKit 编写应用程序的导航结构,然后在 SwiftUI 中编写视图,使用UIHostingViewController.

于 2021-09-27T18:44:54.863 回答