实体定义了个字段id,并通过KVC将json反序列化。
@property (nonatomic, assign) long id;
测试人员提出在iPad Mini ios9.3下闪退。调试发现在调用KVC方法setValuesForKeysWithDictionary:时崩溃了,抛出异常:
NSInvalidArgumentException -[__NSCFString longValue]: unrecognized selector sent to instance
查找资料发现了问题出在32位和64位上
32位编译器
char :1个字节
char*(即指针变量): 4个字节(32位的寻址空间是2^32, 即32个bit,也就是4个字节。同理64位编译器)
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 4个字节
long long: 8个字节
unsigned long: 4个字节
64位编译器
char :1个字节
char*(即指针变量): 8个字节
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 8个字节
long long: 8个字节
先说说64位下运行正常的原因:
在64位下long类型和long long类型都是8个字节,所以64位下id实际类型是long long
而后台返回的json是:{"id":"1"},即id属性是NSString,所以需要将NSString转换成long long类型,NSString转换的相关方法有
@property (readonly) int intValue;
@property (readonly) NSInteger integerValue NS_AVAILABLE(10_5, 2_0);
@property (readonly) long long longLongValue NS_AVAILABLE(10_5, 2_0);
于是通过KVC赋值时通过longLongValue转换成功。
而在32位下,long类型是4个字节,long long类型是8个字节。所以在将NSString转换成long时试图访问longValue属性时报错。
解决方法:
1、后台接口返回json时id值不带双引号,即{"id":1},这样不需要从NSString转换成long类型
2、id字段使用NSInteger类型,NSInteger定义如下:
#if __LP64__ || (TARGET_OS_EMBEDDED && !TARGET_OS_IPHONE) || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif
即在32位下时int,64位下是long,所以32位下NSString转换成int 访问intValue属性即可
3、id字段使用long long类型,都是8个字节。推荐使用,因为后台字段也是Long类型,防止转换时溢出。