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?

+3


source to share


3 answers


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.

+3


source


I assume that due to rule C, all inputs and intermediate results of calculations on the smaller data types are integers. So using !

(or other operators) like BOOL creates an int.



+1


source


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

      

0


source







All Articles