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

SwiftUI:移除JSON数组重复项并在列表视图展示的问题

解决SwiftUI分类列表重复项问题

问题根源

你当前的代码无法去重的核心原因有两个:

  1. CategoryViewModel使用let id = UUID()作为唯一标识,每个实例初始化时都会生成新的UUID——即使两个实例的category完全相同,它们也会被判定为不同的元素,导致去重逻辑失效。
  2. CategoryViewModel没有遵循Hashable协议,而你之前的去重扩展要求数组元素必须是Hashable类型,所以直接调用会报错。

解决方案

步骤1:修改CategoryViewModel,实现稳定标识与Hashable协议

让CategoryViewModel基于category内容来判断相等性,并遵循Hashable,这样去重逻辑才能正确识别重复的分类:

struct CategoryViewModel: Identifiable, Hashable {
    private var application: Application
    
    init(application: Application) {
        self.application = application
    }
    
    // 用category作为稳定的唯一标识,处理nil情况避免冲突
    var id: String {
        category ?? "unknown-category-\(UUID().uuidString)"
    }
    
    var category: String? {
        application.category
    }
    
    // 基于category判断两个实例是否相等
    static func == (lhs: CategoryViewModel, rhs: CategoryViewModel) -> Bool {
        lhs.category == rhs.category
    }
    
    // 基于category生成哈希值
    func hash(into hasher: inout Hasher) {
        hasher.combine(category)
    }
}

步骤2:在ViewModel层实现去重

你可以选择两种方式处理去重:

方式一:利用Set去重(自动去重后排序)

修改CategoryListViewModel的applications计算属性:

var applications: [CategoryViewModel] {
    // 将数组转为Set自动去重,再转回数组并按分类名称排序
    Array(Set(appState.application)).sorted {
        ($0.category ?? "") < ($1.category ?? "")
    }
}

方式二:使用你之前的removingDuplicates()扩展

现在CategoryViewModel已经是Hashable类型,直接调用扩展即可:

var applications: [CategoryViewModel] {
    appState.application.removingDuplicates().sorted {
        ($0.category ?? "") < ($1.category ?? "")
    }
}

方式三:API数据获取后直接处理去重(更高效)

如果不需要保留同一分类下的多个应用实例,可以在获取API数据时直接分组去重,减少后续处理:

func getApps() async {
    do {
        let apiCall = try await Api().fetchApps()
        // 按category分组,取每组第一个实例(确保每个分类只保留一个)
        let uniqueCategoryApps = Dictionary(grouping: apiCall, by: { $0.category })
            .values
            .compactMap { $0.first }
            .map(CategoryViewModel.init)
        
        appState.application = uniqueCategoryApps
    } catch {
        print(error)
    }
}

额外注意事项

  • 处理category为nil的情况:可以将nil分类统一命名为"其他",避免生成大量带UUID的未知分类,提升用户体验。
  • 排序:去重后建议对分类列表排序,保证界面展示的稳定性,避免每次刷新顺序变化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 12:58:14