NSNumber Literals BOOL反向导致objCType类型改变?

时间:2014-08-27 15:39:13

标签: objective-c boolean nsnumber

我在下面测试这些代码:

BOOL b1 = YES;
BOOL b2 = NO;
BOOL b3 = !b1;

NSNumber *num1 = @(b1);
NSNumber *num2 = @(b2);
NSNumber *num3 = @(b3);
NSNumber *num4 = @(!b1);

numj,num2,num3的objCType([num1 objCType])类型是" c",但是num4的objcType是" i"。为什么我反转bool并更改了NSNumber的objcType?

===========================

我的问题是,我的原始代码喜欢这样:

BOOL *m_bFirstEvent;
[pDict setValue:**@[[NSNumber numberWithBool:!m_bFristEvent]]** forKey:@"params"];
NSData *pPostData = [NSJSONSerialization dataWithJSONObject:pDict options:0 error:&pError];
the json string is 
{"method":"getEvent", "id":7, "params":[false]}

在我使用XCode的重构 - >"转换为现代的Objective-c语法"后,代码更改为:

BOOL *m_bFirstEvent;
[pDict setValue:**@[@(!m_bFristEvent)]** forKey:@"params"];
NSData *pPostData = [NSJSONSerialization dataWithJSONObject:pDict options:0 error:&pError];
the json string is 
{"method":"getEvent", "id":7, "params":[0]}

如何避免这种NSNumber Literals错误并安全地使用XCode的重构 - >"转换为现代的Objective-c语法"对于NSNumber Literals?

3 个答案:

答案 0 :(得分:3)

大多数情况下,人们不关心NSNumber是否包含BOOL值,还是值为0或1的整数。当您创建JSON时(可能在处理JSON时),您在乎。

只有[NSNumber numberWithBool:xxx]或[[NSNumber alloc] initWithBool:xxx]创建一个NSNumber,它将在JSON中转换为true或false(而不是1或0)。如果您使用@ YES,@ NO或@(xxx),其中xxx的类型为BOOL,则相同,因为所有这些最终都会调用initWithBool。所以在你的情况下,不幸的是Apple的转换工具做错了。

实际上只有两个包含布尔值的NSNumber对象(显然是一个用于@YES,一个用于@NO)。因此,如果您处理JSON,您可以检查例如

if (jsonResult == @YES)
    NSLog (@"json data contained the value 'true'");
else if (jsonResult == @NO)
    NSLog (@"json data contained the value 'false'");
else if ([jsonResult isKindOfClass:[NSNumber class]])
    NSLog (@"json data contained some kind of number");

这将区分true和false,以及0,1或其他值。是的,与==的比较是有目的和正确的。

@ ((BOOL) xxx)

将创建一个具有bool值的NSNumber。例如

@ ((BOOL) ! myBoolValue)
@ ((BOOL) (x >= 0 && x <= 100)

等等。似乎有时BOOL是签名char,有时它是bool。如果你写

,这会有所不同
@ ((BOOL) 256) // May be @YES or @NO, depending on target
@ ((BOOL) 0.3) // May be @YES or @NO, depending on target

同样,转换为bool而不是BOOL可能会也可能不会创建numberWithBool。两者

@ ((BOOL) (bool) 256)
@ ((BOOL) (bool) 0.3)

将产生值@YES,因为如果值为非零,则转换为bool会产生1,如果值为零,则产生0;这也可以用于C指针或对象指针。

答案 1 :(得分:1)

我认为是由于C的规则,小于int数据类型的计算的所有输入和中间结果都是整数。因此,在BOOL类型上使用!(或其他运算符)会产生一个int。

答案 2 :(得分:0)

那是因为如果您查看BOOL定义,那么您会发现BOOLsigned char。事实上,你不能否定已签名的字符,这意味着它被转换为int然后否定。

修改

bool定义现在略有不同:它直接用于64位设备的bool。来自objc.h档案:

#if !defined(OBJC_HIDE_64) && TARGET_OS_IPHONE && __LP64__
typedef bool BOOL;
#else
typedef signed char BOOL; 
// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" 
// even if -funsigned-char is used.
#endif