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

SwiftUI实现全局统一收藏夹功能及报错修复

问题修复方案

两个问题的根因很明确:

  1. 收藏入口放在分类遍历循环内部,每渲染一个分类就会生成一个重复按钮,且传入的是单分类的主机列表,自然只能看到对应分类下的收藏内容,无法聚合全部分类的收藏项。
  2. 移出入口后调用Favorites()没有传必填的con参数——你的Favorites视图定义中明确要求传入[ConsoleDetails]类型的con属性,空参调用必然触发参数缺失的编译错误。另外原Favorites视图的逻辑也有冗余:遍历全量主机再在循环内判断是否收藏效率低,且页面标题写在列表条目内部会出现重复设置的问题。

具体修改步骤

  • 主菜单拆分为两个独立Section:第一个Section单独放全局收藏入口,第二个Section放分类遍历列表,从结构上避免重复生成收藏按钮。
  • 跳转Favorites视图时传入全量主机数据源ConsoleList.consoles,解决编译报错的同时支持全分类收藏聚合展示。
  • 优化Favorites视图逻辑:先过滤出所有favorites属性为true的主机再渲染列表,把页面标题移到列表外层统一设置。

改后主菜单代码

struct MainMenu: View {
    // 按字母顺序排序主机分类
    var categories = ConsoleList.categories.sorted(by: {$0.key < $1.key})
    var body: some View {
        NavigationView{
            List{
                // 独立收藏入口区块,和分类列表完全隔离
                Section {
                    NavigationLink {
                        // 传入全量主机列表,解决参数缺失问题
                        Favorites(con: ConsoleList.consoles)
                    } label: {
                        Image(systemName: "heart.fill")
                            .foregroundColor(.red)
                        Text("我的收藏")
                            .fontWeight(.semibold)
                    }
                }
                // 主机分类列表区块
                Section {
                    ForEach(categories, id: \.key){ category in
                        NavigationLink(destination: ConsoleMenu(con: category.value)){
                            Image(systemName: "folder")
                                .foregroundColor(.red)
                                .scaledToFit()
                                .frame(height: 30)
                                .cornerRadius(4)
                                .padding(.vertical, 4)
                            Text(category.key)
                                .fontWeight(.semibold)
                        }
                    }
                }
            }
            .navigationTitle("任天堂主机图鉴")
        }
    }
}

优化后收藏页代码

struct Favorites: View {
    var con: [ConsoleDetails]
    // 提前过滤所有收藏的主机,避免循环内重复判断
    private var favoriteConsoles: [ConsoleDetails] {
        con.filter { $0.favorites }
    }
    
    var body: some View {
        List(favoriteConsoles){ cons in
            NavigationLink(destination: ConsoleDetailView(con: cons)){
                Image(cons.imgName)
                    .resizable()
                    .scaledToFit()
                    .frame(height: 50)
                    .cornerRadius(4)
                    .padding(.vertical, 4)
                
                VStack (alignment: .leading){
                    Text(cons.consoleName)
                        .fontWeight(.semibold)
                    if cons.category == "Game & Watch" {
                        Text(cons.mostSoldGame)
                            .font(.subheadline)
                            .foregroundColor(.secondary)
                    }
                }
            }
        }
        // 页面标题移到列表外层,仅设置一次
        .navigationTitle("我的收藏")
        .navigationBarTitleDisplayMode(.inline)
        // 收藏列表为空时可按需添加空态提示
        .overlay {
            if favoriteConsoles.isEmpty {
                ContentUnavailableView("暂无收藏主机", systemImage: "heart.slash", description: Text("你标记的收藏主机都会展示在这里"))
            }
        }
    }
}

struct favorites_Previews: PreviewProvider {
    static var previews: some View {
        NavigationView {
            Favorites(con: ConsoleList.consoles)
        }
    }
}

补充说明

你当前的收藏状态是写死在静态数据里的,如果后续要做用户手动标记/取消收藏的功能,别用静态struct存数据源,换成ObservableObject类用@Published包裹主机列表,否则收藏状态修改后UI不会自动刷新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:57:14