带自定义下标的Swift结构体作为计算属性的递归问题解决
解决方案:打破递归,实现缓存Sum+动态获取其他值
问题核心
原实现的递归死循环源于:计算属性exampleImplementation每次访问都会调用sampleFunc,而sampleFunc又需要获取exampleImplementation["Sum"],这会再次触发计算属性的求值,形成无限递归。
要解决这个问题,关键是拆分逻辑:将Sum的值单独缓存,让sampleFunc直接使用缓存的Sum值,而非通过计算属性获取;同时让非Sum索引的值动态从sampleFunc获取。
具体实现步骤
1. 重构ExampleStruct,支持缓存Sum和动态值提供
调整结构体,让它可以接收缓存的Sum值,以及一个用于获取非Sum值的闭包:
struct ExampleStruct { private var cachedSum: Double private let valueProvider: (String) -> Double? // 初始化:传入缓存的Sum,以及获取其他值的闭包 init(cachedSum: Double, valueProvider: @escaping (String) -> Double?) { self.cachedSum = cachedSum self.valueProvider = valueProvider } subscript(index: String) -> Double? { get { if index == "Sum" { // 访问Sum时直接返回缓存值 return cachedSum } else { // 访问其他索引时,通过闭包动态获取值 return valueProvider(index) } } set { guard let newValue = newValue else { return } if index == "Sum" { // 设置Sum时直接更新缓存 cachedSum = newValue } else { // 设置其他索引时,根据需求更新缓存的Sum // 示例逻辑:用旧值和新值的差更新Sum let oldValue = valueProvider(index) ?? 0 cachedSum = cachedSum - oldValue + newValue } } } }
2. 实现无递归的计算属性exampleImplementation
单独维护缓存的Sum值,让sampleFunc直接使用该缓存值,避免触发计算属性的递归求值:
// 私有存储属性:缓存Sum的值,初始值可根据业务设置 private var cachedSum: Double = 25 var exampleImplementation: ExampleStruct { return ExampleStruct(cachedSum: cachedSum) { index in // 调用sampleFunc时直接传入缓存的Sum,而非访问exampleImplementation["Sum"] let funcResult = sampleFunc(usingSum: cachedSum) return funcResult[index] } } // 调整sampleFunc的签名,接收Sum参数 func sampleFunc(usingSum sum: Double) -> ExampleStruct { // 直接使用传入的sum调用sampleFunc2,避免递归 let sample2Result = sampleFunc2(sum: sum) // 构建并返回ExampleStruct示例,实际逻辑根据业务调整 return ExampleStruct( cachedSum: sum, valueProvider: { key in switch key { case "Ind1": return sample2Result case "Ind2": return 13 default: return nil } } ) } func sampleFunc2(sum: Double) -> Double { // 示例逻辑:根据Sum计算返回值 return sum * 0.5 }
关键说明
- 打破递归:
sampleFunc不再依赖exampleImplementation["Sum"],而是直接使用传入的缓存Sum值,彻底切断递归循环。 - 缓存Sum:
Sum的值单独存储,访问时直接返回,无需重复计算或调用外部方法。 - 动态获取其他值:非
Sum索引的值通过闭包动态从sampleFunc获取,保证数据的实时性。
内容的提问来源于stack exchange,提问作者G J
相关产品推荐
相关产品推荐

