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

SwiftUI列表分类去重及'[AnyHashable:Any]无category成员'报错解决

问题1:[AnyHashable : Any] 无 category 成员报错

报错由三个问题共同导致:

  • 用[String: Any]类型的字典数组存游戏机数据,属于弱类型存储,编译器无法确认字典里存在category字段,自然不支持点语法访问
  • 结构体内部属性初始化顺序错误,定义categories时consoles属性还未完成初始化,编译器无法识别该属性
  • 全局定义的空字符串imgName、category等作为字典key属于冗余代码,无实际作用还容易引发类型推断错误。

解决方案是先定义强类型的Console模型替代字典存储,同时调整结构体内部属性的初始化顺序:

import Foundation

// 强类型游戏机模型,替代原有的字典存储方式
struct Console: Identifiable {
    let id = UUID()
    let imgName: String
    let consoleName: String
    let description: String
    let initialPrice: Double
    let releaseDate: String
    let discontinuation: Int
    let category: String
}

// 结构体名遵循大驼峰命名规范
struct ConsoleList {
    // 先初始化数据源,再做分组逻辑
    let consoles: [Console] = [
        Console(imgName: "FAMICOM",
                consoleName: "Famicom",
                description: "It was released in 1983 in Japan and due to it success it gave birth to the NES",
                initialPrice: 179,
                releaseDate: "Release Date: July 15, 1983",
                discontinuation: 2003,
                category: "Home Consoles"),
        Console(imgName: "NES",
                consoleName: "NES",
                description: "It was released in 1985 in the US and EU and was the european version of the Famicom",
                initialPrice: 179,
                releaseDate: "Release Date: Oct 18, 1985",
                discontinuation: 1991,
                category: "Home Consoles"),
        Console(imgName: "US_SNES",
                consoleName: "SNES, Super Famicom",
                description: "Nintendo released the Super Nintendo Entertainment System, a redesigned version of the Super Famicom, in North America for US$199 (equivalent to $400 in 2021).",
                initialPrice: 199,
                releaseDate: "Release Date: Sept 9, 1991",
                discontinuation: 1999,
                category: "Home Consoles"),
        Console(imgName: "GB_FAT",
                consoleName: "Original GameBoy",
                description: "The Game Boy is the first handheld in the Game Boy family, it was first released in Japan on April 21, 1989.",
                initialPrice: 89.99,
                releaseDate: "Release Date: Apr 21, 1989",
                discontinuation: 2003, // 修正原代码中200的笔误
                category: "Handheld Consoles"),
        Console(imgName: "GB_POCKET",
                consoleName: "GameBoy Pocket",
                description: "On July 21, 1996, Nintendo released the Game Boy Pocket for US$69.99: a smaller, lighter unit that required fewer batteries. It has space for two AAA batteries, which provide approximately 10 hours of gameplay.",
                initialPrice: 69.99,
                releaseDate: "Release Date: Jul 21, 1996",
                discontinuation: 2003,
                category: "Handheld Consoles"),
        Console(imgName: "GB_LIGHT",
                consoleName: "GameBoy Light",
                description: "The Game Boy Light is the second and final revision of the original Game Boy exclusive to Japan.",
                initialPrice: 89.99,
                releaseDate: "Release Date: Apr 14, 1998",
                discontinuation: 2003,
                category: "Handheld Consoles")
    ]
    
    // 计算属性返回分组结果,强类型下可直接通过点语法访问category字段
    var categories: [String: [Console]] {
        Dictionary(grouping: consoles, by: { $0.category })
    }
}
问题2:分类重复展示

重复展示的核心原因是之前弱类型字典+初始化顺序错误导致分组逻辑完全失效。Dictionary(grouping:by:)方法本身返回的字典key就是唯一的分组字段,只要模型和分组逻辑正确,不会出现重复分类。
修正模型后对应调整ContentView代码即可,注意结构体是类型,需要先创建实例才能访问属性,属性名要匹配大小写:

import SwiftUI

struct ContentView: View {
    // 初始化数据源实例
    private let dataSource = ConsoleList()
    
    var body: some View {
        NavigationView{
            // 直接取分组字典的所有key,本身就是唯一值,不会重复
            List(Array(dataSource.categories.keys).sorted(by: >), id: \.self){ category in
                NavigationLink(destination: ConsoleSection()) {
                    HStack {
                        Image(systemName: "folder.fill")
                            .scaledToFit()
                            .frame(height: 30)
                            .cornerRadius(4)
                            .padding(.vertical, 4)
                        Text(category)
                    }
                }
                .navigationTitle("游戏机收藏")
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

补充说明:

  • 原代码中let Con :[consoleDetails] = consoleList.Consoles属于无效代码,引用了不存在的consoleDetails类型和类属性Consoles,直接删除即可
  • 原代码中用VStack包裹单个Text属于冗余布局,换成HStack和Image同行排版效果更合理
  • 如果需要跳转后展示对应分类下的主机列表,给ConsoleSection增加分类入参,从categories字典中取对应key的数组传入即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 02:54:24