我在下面测试这些代码:
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?
答案 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
定义,那么您会发现BOOL
是signed 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