You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI可选择List中能否包含两种不同类型的可选项?

问题描述

我正在开发一款书友会应用,使用NavigationSplitView实现界面布局,左侧的可选择List展示读者列表,点击可查看对应读者的书籍评论;List顶部设有一个“Book”按钮,点击可返回书籍主页面。当前代码如下:

struct ProjectView: View
{
    @State private var readers: [Reader]
    @State private var selectedReader: Reader?
    
    init(readers: [Reader])
    {
        self.readers = readers
    }
    
    var body: some View
    {
        NavigationSplitView
        {
                List(selection: self.$selectedReader)
                {
                    Button("Book")
                    {
                        self.selectedReader = nil
                    }
                    
                    Divider()
                                        
                    ForEach (self.readers, id: \.self)
                    {
                        reader in Text(reader.name)
                    }
                }
        }
        detail:
        {
            if let selectedReader = self.selectedReader
            {
                ReaderView(reader: selectedReader)
            }
            else
            {
                BookView()
            }
        }
        #if os(macOS)
        .navigationSplitViewColumnWidth(min: 180, ideal: 200)
        #endif
        .navigationTitle(self.project.name)
    }
}

希望“Book”按钮能像读者名称选项一样被选中/高亮,请问该如何实现?或者是否可行?

解决方案

完全可行,只需调整选中状态的管理逻辑,让“Book”选项纳入List的选中体系即可,具体实现步骤如下:

  1. 定义枚举统一管理左侧列表的选中项类型,包含书籍主页和读者两种情况:
enum SelectedItem {
    case book
    case reader(Reader)
}
  1. 将原有的selectedReader: Reader?替换为selectedItem: SelectedItem?,默认初始值设为.book(打开页面时默认选中书籍主页):
@State private var selectedItem: SelectedItem? = .book
  1. 修改List的绑定对象为$selectedItem,并给列表元素添加对应tag:

    • 把原Button替换为Text("Book"),设置其tag为.book,点击时自动触发选中状态
    • 读者项的tag设置为.reader(reader),关联对应读者实例
  2. 调整详情视图的判断逻辑,根据selectedItem的类型展示对应页面

完整修改后的代码:

struct ProjectView: View {
    @State private var readers: [Reader]
    @State private var selectedItem: SelectedItem? = .book
    
    init(readers: [Reader]) {
        self.readers = readers
    }
    
    enum SelectedItem {
        case book
        case reader(Reader)
    }
    
    var body: some View {
        NavigationSplitView {
            List(selection: $selectedItem) {
                Text("Book")
                    .tag(SelectedItem.book)
                
                Divider()
                
                ForEach(readers, id: \.self) { reader in
                    Text(reader.name)
                        .tag(SelectedItem.reader(reader))
                }
            }
        } detail: {
            switch selectedItem {
            case .book, nil:
                BookView()
            case .reader(let reader):
                ReaderView(reader: reader)
            }
        }
        #if os(macOS)
        .navigationSplitViewColumnWidth(min: 180, ideal: 200)
        #endif
        .navigationTitle(project.name)
    }
}

修改后,点击“Book”选项会像读者项一样被高亮选中,同时详情页切换到BookView;选中读者项时,对应读者名称高亮并展示ReaderView,完全符合需求。

内容的提问来源于stack exchange,提问作者Ser Pounce

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 10:35:02