SwiftUI中用ForEach从Set生成Toggle列表及Core Data存储问题
问题解答:Toggle列表与Core Data Transformable存储
一、使用Set创建Toggle列表
Set是无序集合,无下标访问能力,且无法直接通过下标创建Binding,需通过以下方式处理:
- 将Set转为数组供ForEach遍历(利用
AllScopes已遵循Identifiable的特性) - 自定义Binding,通过元素的
id定位Set中的元素,修改时替换原元素(值类型属性修改需生成新实例)
示例代码:
struct YearlyReportPage6: View { @Binding var scopes: Set<AllScopes> var body: some View { VStack { // 把Set转为数组,遍历每个Identifiable元素 ForEach(Array(scopes)) { scope in Toggle(isOn: Binding( // 获取当前元素的notify状态 get: { scopes.first(where: { $0.id == scope.id })?.notify ?? false }, // 修改时生成新实例,替换Set中的原元素 set: { newValue in guard let existing = scopes.first(where: { $0.id == scope.id }) else { return } var updatedScope = existing updatedScope.notify = newValue scopes.remove(existing) scopes.insert(updatedScope) } )) { Text(scope.name) } } } } }
二、将数组/字典存储到Core Data的Transformable字段
步骤1:让数据类型遵循Codable
确保数组元素或字典的键值类型遵循Codable协议,以AllScopes为例:
struct AllScopes: Identifiable, Hashable, Codable { var id: UUID var name: String var notify: Bool }
(字典如[String: Bool]本身已满足Codable,无需额外修改)
步骤2:配置Core Data模型
在Xcode的数据模型编辑器中:
- 创建一个Transformable类型的属性(例如命名为
scopesData) - 在右侧检查器中:
- 将Transformer设置为
NSSecureUnarchiveFromDataTransformer(苹果推荐的安全转换方式) - 勾选Allows External Storage(可选,优化大容量数据的存储性能)
- 将Transformer设置为
步骤3:实体类中添加转换逻辑
在Core Data实体的扩展中,添加计算属性来处理数组/字典与Transformable字段的自动转换:
// 假设你的Core Data实体名为Report extension Report { // 数组与Transformable字段的转换 var scopesArray: [AllScopes] { get { guard let data = scopesData as? Data else { return [] } return try? JSONDecoder().decode([AllScopes].self, from: data) ?? [] } set { scopesData = try? JSONEncoder().encode(newValue) } } // 如果是字典,示例如下: var notifyDict: [String: Bool] { get { guard let data = dictData as? Data else { return [:] } return try? JSONDecoder().decode([String: Bool].self, from: data) ?? [:] } set { dictData = try? JSONEncoder().encode(newValue) } } }
注意事项
- 所有嵌套的数据类型必须都遵循
Codable,否则编码/解码会失败 - 避免使用旧的
NSKeyedUnarchiveFromDataTransformer,存在安全风险 - 若需自定义转换逻辑,可以创建继承自
NSSecureUnarchiveFromDataTransformer的子类并注册
内容的提问来源于stack exchange,提问作者mihema
相关产品推荐
相关产品推荐

