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

SwiftUI嵌套遍历模型属性填充allAppliances数组未生效问题

问题原因
  • 核心触发时机错误:你在.onAppear里调用getAllAppliances(),该闭包会在视图首次加载完成时立刻执行,但此时你从JSON异步加载的categories数据还未完成赋值,@State修饰的categories初始值是空数组,三层遍历空数组自然不会向allAppliances写入任何内容。
  • 存在数据重复隐患:当前实现用append直接追加内容,后续视图多次触发.onAppear时(比如从下级页面返回、应用从后台切回前台),会重复写入相同的家电名称,导致列表出现重复项。
  • 额外代码规范问题:SubCategory结构体的SubCategoryTitle属性使用了大驼峰命名,不符合Swift语言小驼峰命名属性的惯例,建议改成subCategoryTitle,避免后续开发出现不必要的混淆。
修复方案

不要依赖.onAppear的触发时机,直接给categories属性添加didSet观察器,只要JSON数据加载完成、给categories赋值成功,就自动生成全量家电列表,从根源上解决时序问题;生成列表前先清空原有数组,避免重复数据。
你可以直接替换成以下核心代码:

struct Category {
    let categoryTitle: String
    var subCategories: [SubCategory]
}

struct SubCategory {
    // 修正命名为小驼峰
    let subCategoryTitle: String
    var appliances: [Appliance]
}

struct Appliance: Identifiable {
    let name: String
    let productID: Int
    var price: Double
    var id: Int { productID }
}

struct MainView: View {
    
    // 给categories添加didSet观察器,数据赋值后自动生成家电列表
    @State private var categories = [Category]() {
        didSet {
            getAllAppliances()
        }
    }
    @State private var allAppliances = [String]()
    
    var body: some View {
        List(allAppliances, id: \.self) {
            Text($0)
        }
        // 移除此处onAppear里的getAllAppliances调用,避免时序错误和重复调用
    }

    func getAllAppliances() {
        // 先清空原有数据,避免重复项
        allAppliances.removeAll()
        // 用flatMap替代三层for循环,逻辑更简洁,效果和手写循环完全一致
        allAppliances = categories
            .flatMap(\.subCategories)
            .flatMap(\.appliances)
            .map(\.name)
        
        // 如果你更习惯手写循环,保留原有写法也可以,只要记得先调用removeAll()即可
    }
}

如果后续要加搜索逻辑,直接基于allAppliances数组做过滤即可,不用再改动层级遍历的逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 21:12:18