所以,这就是问题所在:
答案 0 :(得分:2)
tldr:使用kCFBooleanFalse& kCFBooleanTrue正确检测布尔值!
持有布尔值的NSNumber是__NSCFBoolean私有类的实例,它是一个特殊的野兽 - 指向该类的任何实例的指针将是kCFBooleanFalse或kCFBooleanTrue,这使我们能够使用此代码(ARC):
if ([value isKindOfClass::[NSNumber class]])
{
if ((__bridge CFBooleanRef)value == kCFBooleanTrue)
{
// value == @YES
}
else if ((__bridge CFBooleanRef)value == kCFBooleanFalse)
{
// value == @NO
}
else
{
// value is other type of number (int, float, etc...)
}
}
答案 1 :(得分:1)
答案很简单 - 不要。
您的数据解析器应该知道每个地方的期望值。只是不要混合数字和布尔值。
答案 2 :(得分:1)
不幸的是,无法保证您可以确定用于创建NSNumber
的源类型。 NSNumber
文档声明它与CFNumber
无桥接,换句话说,一个实例可以被视为另一个实例(在ARC的情况下具有适当的桥接转换)。这两种类型的文档都明确指出,虽然可以通过CFNumberGetType()
或objCType
确定存储在任一实例中的值的类型,但这可能不相同用实例构造的类型。这来自CFNumber
文档:
在创建新的CFNumber对象时,不一定会保留对
CFNumberCreate
的调用中指定的类型 - 它使用创建函数认为合适的任何内部存储类型。
如果您检查CFNumberType
,enum
代表CFNumber
中的值类型,则BOOL
没有值。
此外,还有CFBoolean
类型用于存储已包含的布尔值,它未定义为CFNumber
的子类型,或者在其文档中提及或NSNumber
。
如果您创建NSNumber
且值为BOOL
,则发现当前,但结果已被视为{{1}定义的常量值之一没有文档说明这是定义的行为。
因此,为了好奇,您可以尝试解决这个问题,不要依赖于生产代码中的任何特定行为。
注意: CFBoolean
被定义为Core Foundation属性列表类型之一。可以通过使用各种免费桥接关系等证明CFBoolean
必须免费桥接到CFBoolean
。但是我不认为保证来自JSON的布尔必须是NSNumber
实例,尽管可能是 ...
答案 3 :(得分:0)
我提出了另一个解决方案:
id value_from_json = json[key];
if([value_from_json isKindOfClass[NSNumber class]]) {
NSNumber *number_value = (NSNumber *)value_from_json;
// Observe that the check is "isEqualToValue", not "isEqualToNumber"
if([number_value isEqualToValue:@YES] || [number_value isEqualToValue:@NO]) {
// It's a boolean
} else {
// It's not a boolean
}
}
我测试了它,它可以在“true”,true和1之间进行distingush(和“false”,false和0)