iOS 64/32位系统在处理BOOL值时的区别

使用JSONModel时发现在iPhone 5C设备上出现[__NSCFString charValue]: unrecognized selector的报错。

使用JSONModel时发现在iPhone 5C设备上处理BOOL类型数据时出现[__NSCFString charValue]: unrecognized selector的错误。

问题的根本原因是iOS系统BOOL类型在64位和32位机器(包括iPhone 5,iPhone 5C系统都是32位)上定义是不一样的,在objc/objc.h文件中查看定义:

#if OBJC_BOOL_IS_BOOL
    typedef bool BOOL;
#else
#   define OBJC_BOOL_IS_CHAR 1
    typedef signed char BOOL; 
    // BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" 
    // even if -funsigned-char is used.
#endif

#if __has_feature(objc_bool)
#define YES __objc_yes
#define NO  __objc_no
#else
#define YES ((BOOL)1)
#define NO  ((BOOL)0)
#endif

在32位机器上,BOOL值实际上是signed char,而64位机器上BOOL值为bool,bool又被定义为_Bool(stdbool.h)。

#ifndef __STDBOOL_H
#define __STDBOOL_H

/* Don't define bool, true, and false in C++, except as a GNU extension. */
#ifndef __cplusplus
#define bool _Bool
#define true 1
#define false 0
#elif defined(__GNUC__) && !defined(__STRICT_ANSI__)
/* Define _Bool, bool, false, true as a GNU extension. */
#define _Bool bool
#define bool  bool
#define false false
#define true  true
#endif

_Bool在C99中定义为要么是0要么是1:除了0之外的其他输入值全部转为1。

而在32位系统中,由于BOOL值实际上是signed char,所有只要signed char溢出为0时,值就为false,如0,128,256...其他值全为true.

最佳实践

为了兼容iOS 32/64位系统的,在服务端返回BOOL类型的参数时,可以返回:"key": true或"key": 1的形式,考虑到Android系统JAVA在处理0,1到BOOL的转换时可能有问题,推荐使用"key": true的形式。

其它文章

https://stackoverflow.com/questions/31267325/bool-with-64-bit-on-ios/31270249#31270249
iOS安全:修改Mach-O
iOS performSelector使用int等基本数据类型的问题
iOS系统如何获取用户的本机手机号