代码之家  ›  专栏  ›  技术社区  ›  David

从“详细信息”视图返回时(在iPhone上)边栏上的所选项目被迫返回为零

  •  0
  • David  · 技术社区  · 8 月前

    我有一个 导航拆分视图 用一个 边栏 细节 看法从侧边栏中选择项目时,“详细信息”视图将更新以显示所选内容。到目前为止,这一切在iPhone和iPad上都运行良好。

    然而,在iPhone上,当返回侧边栏视图以选择其他内容时, 先前选择的项目被设置为nil .

    在iPad上,它不会将之前选择的项目设置为零,即使你隐藏并显示侧边栏,它仍然会记住之前选择的条目。

    我也试过用iPhone模拟器和物理设备。

    要重现此问题,请参阅下面的小(完整)代码。在模拟器或物理设备上运行它。从侧边栏中选择一个条目,会显示/更新详细信息,显示所选内容。返回到侧边栏视图,您可以在大约半秒钟内看到先前选择的项目仍然处于选中状态,然后将其设置为零。

    为什么在返回边栏视图时,iPhone上的选择会重置为零?

    import SwiftUI
    
    struct ContentView: View {
        @State private var selection: String?
        var body: some View {
            NavigationSplitView {
                SidebarView(selection: $selection)
            } detail: {
                DetailView(selection: $selection)
            }
        }
    }
    
    struct SidebarView: View {
        @Binding var selection: String?
        let people = ["Finn", "Leia", "Luke", "Rey"]
        var body: some View {
            List(people, id: \.self, selection: $selection) { person in
                Text(person)
            }
            Text("selection = \(String(describing: selection))")
        }
    }
    
    struct DetailView: View {
        @Binding var selection: String?
        var body: some View {
            Text("selectedItem = \(String(describing: selection))")
        }
    }
    
    #Preview {
        ContentView()
    }
    

    请参阅下面的GIF。请注意侧边栏屏幕底部。当返回到侧边栏时,你会看到它在很短的半秒钟左右仍然显示之前选择的项目。然后它被清除为零。

    Example showing the issue

    1 回复  |  直到 8 月前
        1
  •  0
  •   Sweeper    8 月前

    只需制作 @State 非可选。然后将其转换为 Binding<String?> 使用其初始化程序之一,然后将其传递给 selection:

    struct ContentView: View {
        @State private var selection: String = "Finn"
        var body: some View {
            NavigationSplitView {
                SidebarView(selection: $selection)
            } detail: {
                DetailView(selection: $selection)
            }
        }
    }
    
    struct SidebarView: View {
        @Binding var selection: String
        let people = ["Finn", "Leia", "Luke", "Rey"]
        var body: some View {
            // note the selection parameter
            List(people, id: \.self, selection: Binding($selection)) { person in
                Text(person)
                    // if you want to indicate the previously selected person more clearly
                    .listRowBackground(selection == person ? Color.gray : nil)
            }
            Text("selection = \(String(describing: selection))")
        }
    }
    
    struct DetailView: View {
        @Binding var selection: String
        var body: some View {
            Text("selectedItem = \(String(describing: selection))")
        }
    }
    

    这将迫使您进行初始选择。如果你不想这样,你可以添加一个新的 状态 在里面 SidebarView ContentView .

    struct SidebarView: View {
        @Binding var selection: String?
        @State private var visitedPerson: String?
        let people = ["Finn", "Leia", "Luke", "Rey"]
        var body: some View {
            Group {
                List(people, id: \.self, selection: $selection) { person in
                    Text(person)
                        // if you want to indicate the previously selected person more clearly
                        .listRowBackground(visitedPerson == person ? Color.gray : nil)
                }
                Text("selection = \(String(describing: visitedPerson))")
            }
            .onChange(of: selection) { oldValue, newValue in
                if let newValue {
                    visitedPerson = newValue
                }
            }
                
        }
    }
    

    也就是说,“强制取消选择”的行为与iOS在其他地方的行为一致。当视图被推到 List 然后弹出 列表 将不会保留其选择。

    例如,请参见:

    struct ContentView: View {
        @State private var items = ["One", "Two", "Three"]
        @State private var selected: String?
        
        var body: some View {
            NavigationStack {
                List(items, id: \.self, selection: $selected) { item in
                    Text(item)
                }
                .toolbar {
                    NavigationLink("Navigate") {
                        Text("Destination")
                    }
                }
            }
            
        }
    }
    

    你也可以比较iPhone和iPad上的设置应用程序,它也有 NavigationSplitView -类似设计。