当前Swift中该计算属性能否正确实现类指针的预期功能?
Swift计算属性访问结构体数组的行为验证
现有代码实现
单例类 hugestuff
class hugestuff { var dataSources: [String: ThingWithIncrediblyLargeArrays] var currentThing: String }
结构体 ThingWithIncrediblyLargeArrays
struct ThingWithIncrediblyLargeArrays { var rawUnsorted: [[String]] var liveSorted: [[String]] var swapValues: [[String]] }
简化访问的计算属性
var hot: ThingWithIncrediblyLargeArrays { get { dataSources[currentThing]! } // 原代码未处理可选值,此处补全强制解包逻辑 set { dataSources[currentThing] = newValue } }
问题验证与分析
结合Swift值类型特性与**写时复制(COW)**机制,对两个问题逐一验证:
(A) 读取数组元素是否会无意义复制数组
执行 x = hugestuff.hot.rawUnsorted[13](修正原问题笔误的enormousArray)时:
- 计算属性
hot的get方法会从dataSources字典中取出对应currentThing的结构体,生成一份结构体副本。但结构体仅包含三个数组的引用,复制开销极小,不会复制数组的底层存储。 - 访问数组元素属于读取操作,Swift数组的COW机制会保证仅持有原数组的引用,不会触发底层存储的复制。
结论:不存在无意义的数组复制,仅会产生开销可忽略的结构体副本。
(B) 修改结构体属性是否能同步到原数据源
执行 hugestuff.hot.liveSorted = ...(修正原问题笔误的searchRows)时:
- 计算属性
hot的get方法返回的是结构体的临时副本,直接修改该副本的属性只会改变副本内容,不会触发计算属性的set方法。 - 临时副本在语句执行结束后会被销毁,原
dataSources中的结构体不会被修改。
结论:无法直接修改原数据源的结构体属性,必须先获取副本修改后再赋值回hot,才能触发set更新原数据,示例代码如下:
var temp = hugestuff.hot temp.liveSorted = newSortedArray hugestuff.hot = temp
优化建议:处理键不存在的情况
可在计算属性的get方法中添加默认值,避免因currentThing不存在于dataSources中导致的崩溃:
var hot: ThingWithIncrediblyLargeArrays { get { dataSources[currentThing] ?? ThingWithIncrediblyLargeArrays( rawUnsorted: [], liveSorted: [], swapValues: [] ) } set { dataSources[currentThing] = newValue } }
内容的提问来源于stack exchange,提问作者Fattie
相关产品推荐
相关产品推荐

