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

SwiftUI实现多选项选择并转为特征对象数组的问题

处理特征多选结果存储与回传格式问题

问题背景

从API获取的响应结构:

"features": [
    {
        "name": "Safety",
        "_id": "636a638959d10a2603b8d645",
        "values": [
            "Array of String"
        ]
    },
    {
        "name": "Entertainment",
        "_id": "636a64312bbe0cd292a1ffc6",
        "values": [
            "Array of String"
        ]
    }
]

使用以下结构体解码:

struct Feature : Codable , Hashable{
    var name : String = ""
    var values : [Value] = []
}

struct Value : Codable, Hashable{
    var value : String = ""
    var unit : String = ""
}

视图渲染逻辑中,用户可从每个特征的选项列表中多选,需要将选中结果存储并生成指定格式的回传JSON:

{
    "features": [
        {
            "Safety": [
                "value1",
                "value9",
                "value3"
            ]
        },
        {
            "Entertainment": [
                "value7",
                "value2",
                "value8"
            ]
        }
    ]
}

解决方案

1. 设计选中状态存储结构

用字典存储每个特征对应的选中值列表,键用特征的name(若存在重名风险,建议用_id更可靠),值为选中的value字符串数组:

@State private var selectedFeatures: [String: [String]] = [:]

2. 绑定选中状态与更新逻辑

修改视图中FeatureCell的选中判断和点击事件,实现选中/取消的逻辑:

ForEach(Array(features.enumerated()), id: \.offset) { featureIndex, feature in
    HStack{
        Text(feature.name).font(Font.body.bold())
        Spacer()
    }.padding(.bottom , 10)
    ScrollView(.horizontal, showsIndicators: false){
        HStack(spacing : 10){
            ForEach(Array(feature.values.enumerated()), id: \.offset) { valueIndex, value in
                // 判断当前值是否已选中
                let isSelected = selectedFeatures[feature.name]?.contains(value.value) ?? false
                FeatureCell(isSelected: .constant(isSelected), value: value)
                    .onTapGesture {
                        // 更新选中列表
                        if var selectedValues = selectedFeatures[feature.name] {
                            if isSelected {
                                // 取消选中:移除对应值
                                selectedValues.removeAll { $0 == value.value }
                            } else {
                                // 选中:添加对应值
                                selectedValues.append(value.value)
                            }
                            selectedFeatures[feature.name] = selectedValues
                        } else {
                            // 首次选中:初始化数组
                            selectedFeatures[feature.name] = [value.value]
                        }
                    }
            }
        }
        Divider().padding(10)
    }
}.padding(15)

3. 生成指定格式的回传JSON

将字典转换为要求的数组格式,再编码为JSON:

// 转换为目标格式:每个元素是单个键值对的字典
let outputFeatures = selectedFeatures.map { [ $0.key: $0.value ] }
let outputDictionary = ["features": outputFeatures]

// 编码为JSON数据
do {
    let jsonData = try JSONSerialization.data(withJSONObject: outputDictionary, options: .prettyPrinted)
    if let jsonString = String(data: jsonData, encoding: .utf8) {
        // 此处可将jsonString发送至API
        print(jsonString)
    }
} catch {
    print("JSON编码错误:\(error)")
}

优化建议

如果特征存在重名情况,建议用_id作为字典的键,生成JSON时再替换为name,避免冲突:

// 存储时用_id
@State private var selectedFeatures: [String: [String]] = [:]

// 生成JSON时转换
let outputFeatures = selectedFeatures.compactMap { featureId, selectedValues in
    guard let feature = features.first(where: { $0._id == featureId }) else { return nil }
    return [feature.name: selectedValues]
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 04:05:40