先看一段代码:
NSDictionary *dict = [self dictFromResponseObject:responseData];
CYBasicResponce *response = [responseClass mj_objectWithKeyValues:dict];
上面的代码看起来很和谐,就是把从后台请求获取到的字典(底层库处理了JSON解析)转换成对象,以供处理数据逻辑。但是谁曾想这里有个大坑呢,就像我在下边注释里写的。
/** mj_objectWithKeyValues:方法中将数值类型数据先转
double型,再转回来,比如说long long型数值a,会先被转为(double)a;
再转回(long long)a;对于大多数数字不会有什么问题,但是当整数有效值
长度超过15时,由于浮点数的取舍问题,这个值会发生变化,不再是你之前以为
的样子。对的,我们的uid就是这样的一个大数,不然我怎么会遭遇这个bug,并
且在这里写上这么长一段注释🐶。
156939277061174208 //转化后uid
156939277061174202 //实际uid
代码可证:
long long a = 15693927706117420;
double b = (double)a;
long long c = (long long)b;
printf("A = %lld\n",a);
printf("B = %f\n",b);
printf("C = %lld\n",c);
Console:
A = 15693927706117420
B = 15693927706117420.000000
C = 15693927706117420
Program ended with exit code: 0
解决方法:
将uid特殊处理,重新set。
*/
NSNumber *uid = dict[@"uid"];
if (uid) {
[response setValue:uid forKey:@"uid"];
}
问题代码在NSObject+MJKeyValue.h这个文件的第163行(我用的是3.1.2版本),如下:
162 NSDecimalNumber *decimalValue = [NSDecimalNumber decimalNumberWithString:oldValue];
163 value = decimalValue == [NSDecimalNumber notANumber] ? @(0) : @(decimalValue.doubleValue);
查了下原因,大致可以归结到浮点数的向偶舍入,其间的技术细节这位大神在系列博客里说的很清楚,有兴趣有时间可以读下。
网友评论