如何修改Swift枚举类中的只读items属性值?
解决枚举只读属性无法修改的问题
问题根源
你定义的ShopItemSelection枚举中,items是只读计算属性(仅包含get逻辑),因此无法直接赋值修改。要实现动态过滤.clothes的需求,以下是几种优雅的解决方案:
方案一:给枚举添加关联值,支持动态过滤标记
通过给枚举case添加默认关联值,控制是否过滤指定元素,既保留枚举的默认值特性,又能灵活调整返回的items:
import Foundation enum ShopItemSelection: Hashable { // 给case添加默认关联值,默认不排除clothes case ralph(excludeClothes: Bool = false) case target(excludeClothes: Bool = false) var items: [ShopItem] { // 先获取对应case的基础items数组 let baseItems: [ShopItem] switch self { case .ralph: baseItems = [.meat, .clothes, .fruit] case .target: baseItems = [.meat, .clothes, .fruit, .veggies] } // 根据关联值判断是否过滤.clothes switch self { case .ralph(let exclude), .target(let exclude): return exclude ? baseItems.filter { $0 != .clothes } : baseItems } } }
使用时直接在初始化枚举时传入过滤标记:
var sections: [ShopItemSelection] = [] switch store.size { case "SMALL": sections.append(.ralph(excludeClothes: !store.stillHaveClothes)) default: sections.append(.target(excludeClothes: !store.stillHaveClothes)) } return sections
方案二:用结构体包装枚举,实现自定义items
如果不想修改原有枚举的定义,可以创建一个结构体来包装枚举类型和自定义items,通过结构体的可变属性实现动态修改:
// 保持原有枚举不变 enum ShopItemSelection: Hashable { case ralph case target var items: [ShopItem] { switch self { case .ralph: return [.meat, .clothes, .fruit] case .target: return [.meat, .clothes, .fruit, .veggies] } } } // 新增包装结构体 struct ShopSection { let type: ShopItemSelection var customItems: [ShopItem]? // 对外暴露统一的items访问入口 var items: [ShopItem] { return customItems ?? type.items } }
使用时通过修改结构体的customItems属性实现过滤:
var sections: [ShopSection] = [] switch store.size { case "SMALL": sections.append(ShopSection(type: .ralph)) default: sections.append(ShopSection(type: .target)) } if !store.stillHaveClothes { sections[0].customItems = sections[0].type.items.filter { $0 != .clothes } } return sections
方案三:给枚举添加存储属性(不推荐)
这种方式会让枚举带有可变状态,破坏枚举作为纯值类型的设计初衷,仅在特殊场景下使用:
enum ShopItemSelection: Hashable { case ralph case target // 存储过滤后的数组,默认nil时使用基础items private var filteredItems: [ShopItem]? var items: [ShopItem] { get { return filteredItems ?? baseItems } set { filteredItems = newValue } } // 提取基础items到私有计算属性 private var baseItems: [ShopItem] { switch self { case .ralph: return [.meat, .clothes, .fruit] case .target: return [.meat, .clothes, .fruit, .veggies] } } }
此时你原来的代码可以直接运行,因为items现在有了setter方法。
内容的提问来源于stack exchange,提问作者Seb
相关产品推荐
相关产品推荐

