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

问题描述 投票:0回答:1

我有一个 NavigationSplitView ,带有 SidebarDetail 视图。从侧边栏中选择项目时,详细信息视图会更新以显示所选内容。到目前为止,这一切在 iPhone 和 iPad 上都运行良好。

但是,在 iPhone 上,当返回侧边栏视图选择其他内容时,之前选择的项目将被设置为 nil

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

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

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

返回侧边栏视图时,为什么 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。注意屏幕底部的侧边栏。返回侧边栏时,您会看到它仍然显示先前选择的项目,时间很短,大约半秒左右。然后它就被清零了。

list swiftui selection navigationsplitview
1个回答
0
投票

只需将

@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))")
    }
}

这迫使您做出初步选择。如果您不希望这样,您可以在

@State
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
顶部然后弹出时,
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")
                }
            }
        }
        
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.