It's just syntax, there's no technical reason for it. They just use YES/NO for their BOOL instead of true/false like c++ does.
Boolean Variables and Data Type ( or lack thereof in C )A true boolean data type could be used for storing logical values, and would only have two legal values - "true", and "false". C does not have boolean data types, and normally uses integers for boolean testing.
By convention, we use the BOOL type for Boolean parameters, properties, and instance variables and use YES and NO when representing literal Boolean values. Because NULL and nil zero values, they evaluate to “false” in conditional expressions.
A Boolean or truth value can be True and False , or, equivalently, the number 1 or 0.
I believe there is a difference between bool
and BOOL
, check out this webpage for an explanation of why:
http://iosdevelopertips.com/objective-c/of-bool-and-yes.html
Because BOOL
is an unsigned char
rather than a primitive type, variables of type BOOL
can contain values other than YES
and NO
.
Consider this code:
BOOL b = 42;
if (b) {
printf("b is not NO!\n");
}
if (b != YES) {
printf("b is not YES!\n");
}
The output is:
b is not NO!
b is not YES!
For most people this is an unnecessary concern, but if you really want a boolean it is better to use a bool
. I should add: the iOS SDK generally uses BOOL
on its interface definitions, so that is an argument to stick with BOOL
.
There is no practical difference provided you use BOOL
variables as booleans. C processes boolean expressions based on whether they evaluate to 0 or not 0. So:
if(someVar ) { ... }
if(!someVar) { ... }
means the same as
if(someVar!=0) { ... }
if(someVar==0) { ... }
which is why you can evaluate any primitive type or expression as a boolean test (including, e.g. pointers). Note that you should do the former, not the latter.
Note that there is a difference if you assign obtuse values to a so-called BOOL
variable and test for specific values, so always use them as booleans and only assign them from their #define
values.
Importantly, never test booleans using a character comparison -- it's not only risky because someVar
could be assigned a non-zero value which is not YES, but, in my opinion more importantly, it fails to express the intent correctly:
if(someVar==YES) { ... } // don't do this!
if(someVar==NO ) { ... } // don't do this either!
In other words, use constructs as they are intended and documented to be used and you'll spare yourself from a world of hurt in C.
I did an exhaustive test on this. My results should speak for themselves:
//These will all print "1"
NSLog(@"%d", true == true);
NSLog(@"%d", TRUE == true);
NSLog(@"%d", YES == true);
NSLog(@"%d", true == TRUE);
NSLog(@"%d", TRUE == TRUE);
NSLog(@"%d", YES == TRUE);
NSLog(@"%d", true == YES);
NSLog(@"%d", TRUE == YES);
NSLog(@"%d", YES == YES);
NSLog(@"%d", false == false);
NSLog(@"%d", FALSE == false);
NSLog(@"%d", NO == false);
NSLog(@"%d", false == FALSE);
NSLog(@"%d", FALSE == FALSE);
NSLog(@"%d", NO == FALSE);
NSLog(@"%d", false == NO);
NSLog(@"%d", FALSE == NO);
NSLog(@"%d", NO == NO);
//These will all print "0"
NSLog(@"%d", false == true);
NSLog(@"%d", FALSE == true);
NSLog(@"%d", NO == true);
NSLog(@"%d", false == TRUE);
NSLog(@"%d", FALSE == TRUE);
NSLog(@"%d", NO == TRUE);
NSLog(@"%d", false == YES);
NSLog(@"%d", FALSE == YES);
NSLog(@"%d", NO == YES);
NSLog(@"%d", true == false);
NSLog(@"%d", TRUE == false);
NSLog(@"%d", YES == false);
NSLog(@"%d", true == FALSE);
NSLog(@"%d", TRUE == FALSE);
NSLog(@"%d", YES == FALSE);
NSLog(@"%d", true == NO);
NSLog(@"%d", TRUE == NO);
NSLog(@"%d", YES == NO);
The output is:
2013-02-19 20:30:37.061 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.061 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.072 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.073 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.073 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.074 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.074 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.075 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.075 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.076 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.077 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.077 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.078 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.078 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.079 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.079 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.080 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.080 BooleanTests[27433:a0f] 1
2013-02-19 20:30:37.081 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.081 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.082 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.091 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.092 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.093 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.093 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.094 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.094 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.095 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.095 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.096 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.096 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.097 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.098 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.101 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.102 BooleanTests[27433:a0f] 0
2013-02-19 20:30:37.102 BooleanTests[27433:a0f] 0
You might want to read the answers to this question. In summary, in Objective-C (from the definition in objc.h):
typedef signed char BOOL;
// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C"
// even if -funsigned-char is used.
#define OBJC_BOOL_DEFINED
#define YES (BOOL)1
#define NO (BOOL)0
The main (dangerous!) difference between true
and YES
is in JSON serialization.
For example, we have JSON-type server request and need to send true/false in json sence:
NSDictionary *r1 = @{@"bool" : @(true)};
NSDictionary *r2 = @{@"bool" : @(YES)};
NSDictionary *r3 = @{@"bool" : @((BOOL)true)};
Then we convert it to JSON string before sending as
NSData *data = [NSJSONSerialization dataWithJSONObject:requestParams options:0 error:nil];
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
The result is
jsonString1 // {"bool":1}
jsonString2 // {"bool":true}
jsonString3 // {"bool":true}
Due to API logic jsonString1
could result in an error.
So be careful with booleans in Objective-C.
To sum up, only exact @YES
and casted value as @((BOOL)expression)
are of __NSCFBoolean
type and converted to true
with JSON serialization.
Any other expressions like @(expression1 && expression2)
(even @(YES && YES)
) are of __NSCFNumber (int)
type and converted to 1
in JSON.
P.S. You can simply use string-valued boolean
@{@"bool" : @"true"}; // in JSON {"bool":true}
There is a subtle bug that no one has mentioned here, that I thought I would include... more of a logical error than anything:
int i = 2;
if(i); //true
if(i==YES); // false
if((!!i)==YES); //true
so the issue here is just that (YES==1)
and in C the comparison isn't a boolean one, but one based on value.
because YES
is just a #define
(rather than something intrinsic to the language), it has to be some value, and 1
makes the most sense.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With