消除包含大量导航视图的SwiftUI工作表

lrpiutwd  于 2023-02-07  发布在  Swift
关注(0)|答案(2)|浏览(125)

我有一个按钮,可以打开一个工作表中的配置文件和设置视图,其中有其他导航视图。
我知道如何关闭工作表,但此方法似乎不适用于其他导航视图,因为当我更深入地进入导航并点击“完成”关闭工作表时,它只会让我返回到上一个导航视图,直到我返回到主“配置文件和设置”视图。

带按钮的视图:

import SwiftUI

struct TodayView: View {
    @State private var showSheet = false
    
    var body: some View {
        NavigationView {
            ScrollView {
                VStack(alignment: .leading) {
                    
                    TodayTabDateComponent()
                        .padding(.top, -10)
                    
                    ForEach(0 ..< 32) { item in
                        VStack(alignment: .leading) {
                            Text("Title")
                            Text("Description")
                        }
                        .padding(.vertical)
                    }
                }
                .frame(maxWidth: .infinity, alignment: .leading)
                .padding(.horizontal)
            }
            .navigationTitle("Today")
            
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button(action: {
                        showSheet = true
                    }, label: {
                        Image(systemName: "person.circle.fill")
                            .foregroundColor(.primary)
                    })
                    .sheet(isPresented: $showSheet) {
                        ProfileAndSettingsView()
                    }
                }
            }
        }
    }
}

struct TodayView_Previews: PreviewProvider {
    static var previews: some View {
        TodayView()
    }
}

“配置文件和设置”视图:

import SwiftUI

struct ProfileAndSettingsView: View {
    @Environment(\.presentationMode) var presentationMode
    
    var body: some View {
        NavigationView {
            VStack {
                List {
                    Section {
                        NavigationLink {
                            UserProfileView()
                        } label: {
                            HStack(alignment: .center) {
                                Image("avatar")
                                    .resizable()
                                    .aspectRatio(contentMode: .fit)
                                    .clipShape(Circle())
                                    .frame(width: 60, height: 60)
                                
                                VStack(alignment: .leading) {
                                    Text("Name Surname")
                                        .font(.title2)
                                        .fontWeight(.bold)
                                    
                                    Text("Profile Settings, Feed Preferences\n& Linked Accounts")
                                        .font(.caption)
                                }
                            }
                        }
                        .padding(.vertical, 6)
                    }            }
                .listStyle(.insetGrouped)
                
                .navigationTitle("Profile & Settings")
                .navigationBarTitleDisplayMode(.inline)
                
                .toolbar {
                    ToolbarItem(placement: .navigationBarTrailing) {
                        Button {
                            presentationMode.wrappedValue.dismiss()
                        } label: {
                            Text("Done")
                        }
                    }
                }
            }
        }
    }
}

struct ProfileAndSettingsView_Previews: PreviewProvider {
    
    static var previews: some View {
        ProfileAndSettingsView()
    }
}

我已经调查了这个问题,但找不到任何可行的解决办法。

roejwanj

roejwanj1#

你的问题是你把.sheet应用到工具栏里面的按钮上吗?我认为你需要把它应用到NavigationView本身上?

import SwiftUI

struct TodayView: View {
    @State private var showSheet = false
    
    var body: some View {
        NavigationView {
            ....
            }
            .navigationTitle("Today")
            .toolbar {
                ToolbarItem(placement: .navigationBarLeading) {
                    Button(action: {
                        showSheet = true
                    }, label: {
                        Image(systemName: "person.circle.fill")
                            .foregroundColor(.primary)
                    })
                }
            }
            .sheet(isPresented: $showSheet) {
                ProfileAndSettingsView()
            }
        }
    }
}
oxcyiej7

oxcyiej72#

如果你的目标是iOS15或更高版本,不要使用presentationMode,而是使用@Environment(\.isPresented) private var isPresented,这将执行你想要的操作。
presentationMode已弃用,并已替换为isPresenteddismiss
我认为presentationMode执行的操作与dismiss执行的操作类似,根据Apple Docs(在dismiss上)
如果这样做,工作表将无法关闭,因为该操作应用于声明它的环境,即详细信息视图的环境,而不是工作表的环境。实际上,如果您在NavigationView中显示详细信息视图,解除操作会弹出导航堆栈中的详细视图。解除操作对当前未显示的视图没有影响。如果需要查询SwiftUI当前是否正在显示视图,请读取isPresented环境值。
如果您的目标是较低的iOS版本,您可以创建自己的密钥,如下所示

struct SheetOpen: EnvironmentKey {
    static var defaultValue: Binding<Bool> = .constant(false)
}

extension EnvironmentValues {
    var sheetOpen: Binding<Bool> {
        get { self[SheetOpen.self] }
        set { self[SheetOpen.self] = newValue }
    }
}

在定义工作表的位置执行此操作

.sheet(isPresented: $showSheet) {
    ProfileAndSettingsView()
        .environment(\.sheetOpen, $showSheet)
}

然后,您可以像使用任何其他环境变量一样使用它

@Environment(\.sheetOpen) var sheetOpen

要消除它,只需执行sheetOpen.wrappedValue.toggle()

相关问题