IOS KVC 32位和64位的坑

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cuihaiyang/article/details/71716529

实体定义了个字段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类型,防止转换时溢出。

猜你喜欢

转载自blog.csdn.net/cuihaiyang/article/details/71716529