Swift中Identifiable结构体多属性生成UInt类型id编译失败的解决方法
问题修复方案
你的代码编译失败主要有三个核心问题,逐个解决就能正常运行:
1. 语法错误:括号不匹配
原代码里的括号嵌套混乱,多了一个右括号,最后一行也没闭合所有括号。比如第二行的((i3 << 45) + (i4 << 40)))多了一个),最后一行的((i11 << 5) + i12缺少闭合的)))。
2. 类型不匹配:UInt64转UInt32
Swift里UInt默认是64位(在64位平台),位移后的结果是UInt64类型,但你要返回UInt32,必须显式转换,否则编译器会报错。
3. 逻辑缺陷:位数溢出导致ID冲突
UInt32只有32位,但你现在给12个属性每个分配5位(12*5=60位),远超过32位的容量,最终转换时会截断高位,大概率会出现不同对象生成相同ID的情况,完全达不到唯一标识的目的。
修复后的代码方案(推荐用哈希生成,更可靠)
如果只是为了生成能用于对象比较的唯一ID,没必要手动位移组合,Swift的Hasher可以高效组合多个属性生成哈希值,既简洁又能避免位数溢出问题:
struct OBJ: Identifiable { var i1: UInt var i2: UInt var i3: UInt var i4: UInt var i5: UInt var i6: UInt var i7: UInt var i8: UInt var i9: UInt var i10: UInt var i11: UInt var i12: UInt var id: UInt32 { var hasher = Hasher() hasher.combine(i1) hasher.combine(i2) hasher.combine(i3) hasher.combine(i4) hasher.combine(i5) hasher.combine(i6) hasher.combine(i7) hasher.combine(i8) hasher.combine(i9) hasher.combine(i10) hasher.combine(i11) hasher.combine(i12) return UInt32(hasher.finalize()) } }
如果你坚持手动位移(需调整位数)
如果一定要用位移的方式,必须把总位数控制在32位以内,比如给每个属性分配2位(12*2=24位,剩下8位留空),同时修正语法和类型转换:
struct OBJ: Identifiable { var i1: UInt var i2: UInt var i3: UInt var i4: UInt var i5: UInt var i6: UInt var i7: UInt var i8: UInt var i9: UInt var i10: UInt var i11: UInt var i12: UInt var id: UInt32 { // 先把每个属性截断到2位,再位移组合 let part1 = (i1 & 0b11) << 22 let part2 = (i2 & 0b11) << 20 let part3 = (i3 & 0b11) << 18 let part4 = (i4 & 0b11) << 16 let part5 = (i5 & 0b11) << 14 let part6 = (i6 & 0b11) << 12 let part7 = (i7 & 0b11) << 10 let part8 = (i8 & 0b11) << 8 let part9 = (i9 & 0b11) << 6 let part10 = (i10 & 0b11) << 4 let part11 = (i11 & 0b11) << 2 let part12 = i12 & 0b11 return UInt32(part1 | part2 | part3 | part4 | part5 | part6 | part7 | part8 | part9 | part10 | part11 | part12) } }
注意:手动位移的方式很容易因为属性值超过分配的位数导致ID冲突,所以更推荐用Hasher的方案。
内容的提问来源于stack exchange,提问作者Pusik Park
相关产品推荐
相关产品推荐

