从第三方库生成的NSValue中提取CGPoint时出现字节大小不匹配错误的技术问询
解决NSValue获取CGPoint时的字节不匹配错误
首先拆解下问题的本质:
你遇到的错误提示“无法获取大小为16字节的值。编码类型为{?={CGPoint=dd}d}的对象预期大小应为24字节”,结合你打印的NSValue长度都是24字节,说明第三方库生成的NSValue并不是单纯封装了CGPoint,而是封装了一个包含CGPoint和一个额外double类型数据的复合结构体(CGPoint本身是2个double,占16字节,加上一个double刚好24字节)。虽然p.objCType打印的是{CGPoint=dd},但这应该是第三方库的错误或者误导性设置,实际存储的内存结构是更大的复合结构。
至于Debug模式下直接用[p getValue:&pointValue]能临时工作,是因为Debug模式编译器没有做严格的内存优化,刚好读取了前16字节的CGPoint数据;但Release模式下编译器会做内存对齐、代码优化,直接读取16字节会触发内存访问越界,导致崩溃。
正确的解决方案
我们需要按照NSValue实际存储的结构来读取数据:
- 先定义一个和NSValue内部存储匹配的结构体:
typedef struct { CGPoint point; double extraData; // 对应额外的8字节数据 } PointWithExtraData;
- 遍历数组时,读取整个结构体再提取CGPoint:
for (NSValue *p in array) { PointWithExtraData storedData; [p getValue:&storedData]; // 提取需要的CGPoint CGPoint pointValue = storedData.point; // 这里可以正常使用pointValue了,extraData如果不需要可以忽略 }
验证说明
你可以尝试打印storedData.extraData的值,如果能得到一个合理的数值(比如某些额外参数、权重之类的),就说明我们的结构体定义完全匹配第三方库的存储结构。
内容的提问来源于stack exchange,提问作者Mario Monaco
相关产品推荐
相关产品推荐

