NSNumber BOOL literals reverse reason objCType type change?
I am testing these codes below:
BOOL b1 = YES;
BOOL b2 = NO;
BOOL b3 = !b1;
NSNumber *num1 = @(b1);
NSNumber *num2 = @(b2);
NSNumber *num3 = @(b3);
NSNumber *num4 = @(!b1);
objCType ([num1 objCType]) type num1, num2, num3 is "c", but objcType for num4 is "i". Why am I canceling bool and objcType NSNumber changed?
============================
My problem is my origin code like this:
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]}
after i use XCode refactor -> "convert to modern Objective-c syntax" the code changes to:
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]}
How can I avoid this NSNumber literal error and safely use XCode refactor -> "convert to modern Objective-c syntax" for NSNumber literals?
source to share
In most cases, people don't care if NSNumber contains a BOOL value or an integer with a value of 0 or 1. When you create JSON (and possibly when processing JSON), you don't care.
Only [NSNumber numberWithBool: xxx] or [[NSNumber alloc] initWithBool: xxx] creates an NSNumber which will be converted to true or false (not 1 or 0) in JSON. It's the same if you use @YES, @NO, or @ (xxx) where xxx is of type BOOL, because it all ends up calling initWithBool. So in your case, unfortunately, Apple's conversion tool did the wrong thing.
There are actually only two NSNumber objects containing booleans that have ever existed (obviously one for @YES and one for @NO). So if you are processing JSON you can check for example
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");
and this will distinguish between true and false, and 0, 1, or other values. Yes, comparison with == is done on purpose and correctly.
@ ((BOOL) xxx)
will create NSNumber with bool value. for example
@ ((BOOL) ! myBoolValue)
@ ((BOOL) (x >= 0 && x <= 100)
etc. It looks like sometimes BOOL is signed by char and sometimes by bool. It matters if you write
@ ((BOOL) 256) // May be @YES or @NO, depending on target
@ ((BOOL) 0.3) // May be @YES or @NO, depending on target
Likewise, casting to bool instead of BOOL may or may not create numberWithBool. Both
@ ((BOOL) (bool) 256)
@ ((BOOL) (bool) 0.3)
will return the value @YES, because the cast to bool gives 1 if the value was nonzero and 0 if it was zero; this can also be used with C pointers or object pointers.
source to share
This is because if you look at the definition BOOL
, then you will understand what it BOOL
is signed char
. You cannot actually nullify a signed char, which means it is cast in int
and then negation occurs.
EDIT
The definition of bool is now slightly different: it is passed directly to bool for 64-bit devices. From file 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
source to share