How to compare @NO and @YES with elegance and without risk of false positives/negatives?
Solution 1
What is condition
? Is it a BOOL
or an NSNumber
?
If condition
is a BOOL
, then you don't want to use @NO
or @YES
at all. You want to say
if (condition) // test if condition is true
if (!condition) // test if condition is false
if (condition == NO) // same as previous, based on personal preference
Note that you should never say
if (condition == YES)
because BOOL
isn't actually restricted to 0
and 1
as values, it can hold anything in char
, so if condition
accidentally holds, say, 3
, then if (condition)
and if (condition == YES)
would behave differently.
If condition
is an NSNumber
, then you still don't want to use @NO
and @YES
. You just want to convert it to a BOOL
using -boolValue
, as in
if ([condition boolValue]) // test if condition is true
if (![condition boolValue]) // test if condition is false
if ([condition boolValue] == NO) // same as previous, based on personal preference
The basic takeaway here is, don't use @NO
and @YES
literals for comparisons. It's pointless, and inelegant, since all you'd be able to do with them is convert them back into BOOL
s.
Solution 2
Assuming the data type of condition
is BOOL
, then you want:
if (condition) {
// true (YES)
} else {
// false (NO)
}
If condition is an NSNumber
then use:
if ([condition boolValue]) {
// true (YES)
} else {
// false (NO)
}
If condition
is based on some arbitrary numbers then treat 0
as NO
and treat non-zero as YES
.
Again, if condition
is an NSNumber
then do:
if ([condition intValue]) {
// non-zero - true (YES)
} else {
// zero - false (NO)
}
Update: Based on the following comment from the OP:
Condition is a bool, like if (myView.frame.size.height == 30)
This implies that the actual question wanted to do checks something like:
if ((myView.frame.size.height == 30) == YES)
This is very unusual. The proper thing to do is:
if (myView.frame.size.height == 30) {
// true - height is 30
} else {
// false - height is not 30
}
There is no need to worry about false positives or negatives. The condition is either true or it isn't. There is no 3rd possibility. If the condition gives the wrong result then the solution is to fix the condition.
Solution 3
You can save @NO in a dictionary because @NO is an object. You cannot save NO in a dictionary. So use @NO.boolValue when needed. For example:
NSDictionary *userSetting = (NSDictionary *)[[NSUserDefaults standardUserDefaults] objectForKey:@"user"];
//Suppose you have done: userSetting[@"canWriteCode"] = @YES;
if ([userSetting[@"canWriteCode"] boolValue])
[self helloProgrammer];
zakdances
Updated on June 06, 2022Comments
-
zakdances almost 2 years
I want to use bool literals like
if (condition == @NO) { } else if (condition == @YES) { {
When I try this, XCode wants me to use NSNumber methods to compare, like isEqualTo. Is there a simpler way to do this (without isEqualTo)? If I can't, should I use isEqualTo, isEqualToValue, or isEqualToNumber?
-
zakdances about 11 yearsWhat numbers trigger @NO or @YES?
-
rmaddy about 11 yearsNone directly. If
condition
is created from[NSNumber numberWithBool:]
then you compare against@YES
or@NO
. -
Carl Veazey about 11 yearsComparing to
YES
may be problematic in some cases. And +1 for not using dot syntax for a non-property method call. -
rmaddy about 11 years@yourfriendzak Notice all of the options. This is because you haven't been clear. What type is
condition
? How have you created its value? -
rmaddy about 11 years@CarlVeazey Yes, until we get more details about the type of
condition
and how its value is set, it's difficult to nail down the proper solution. -
rmaddy about 11 yearsI don't know why this was downvoted. If
condition
is anNSNumber
and the OP doesn't want to useisEqual:
, then this is actually one possible solution. -
Lily Ballard about 11 yearsA few bad answers in here. Never ever say
condition == YES
, becauseBOOL
isn't a true boolean value and therefore may have a non-zero value that's not the same asYES
. Similarly[condition isEqual:@YES]
would only work ifcondition
was constructed fromYES
to begin with; if it's a non-zero non-YES
value, that will also fail. And of course[condition boolValue] == YES
is also bad. -
rmaddy about 11 years@KevinBallard If
BOOL
values are only used withYES
orNO
then what I have is just fine. Personally, anyone that assigns any other value to aBOOL
variable is asking for trouble (and it using it wrong). What I have posted will never be a problem in my own code because I only use the proper values withBOOL
values. -
rmaddy about 11 years@KevinBallard Once the OP chimes in here and tells us what he really has, more precise answers can be given.
-
Lily Ballard about 11 years@rmaddy: Regardless of what you do personally, it's a really bad idea to give out advice like this to other people. The simple fact is,
if (boolValue == YES)
is not the same thing asif (boolValue)
, with the former unexpectedly evaluating the condition to0
in some cases. -
Lily Ballard about 11 yearsWhy would you ever say
@NO.boolValue
instead of just sayingNO
? -
rmaddy about 11 years@KevinBallard I only use
if (value)
orif (!value)
myself. Again, until the OP chimes in, my answer is tailored to the style of the original code. -
Lily Ballard about 11 years@rmaddy: It's still bad advice. Code that behaves correctly trumps matching style every time.
-
anticyclope about 11 years> I want to use bool literals
-
rmaddy about 11 years@KevinBallard Personally I wouldn't but it is valid.
-
zakdances about 11 yearsCondition is a bool, like if (myView.frame.size.height == 30)
-
rmaddy about 11 years@yourfriendzak So
condition
isn't a variable of typeBOOL
orNSNumber
? Now your question makes no sense. Why would you do something likeif ((myView.frame.size.height == 30) == YES)
? Is that what you are really asking? -
zakdances about 11 years@rmaddy Yes, I wanted to evaluate nested expressions. Sorry for the confusion.
-
rmaddy about 11 years@yourfriendzak Please see the update I added to the end of my original answer. Does this now answer your question?
-
Jelle about 11 years@maddy Valid yes, but just as pointless as converting NO to a string "nooohoooo" and parsing that string back to a BOOL, right?
-
zakdances about 11 years@rmaddy It's people like you that make SO such an amazing place.
-
borrrden about 11 yearsNote that !condition and condition == NO are not the same. There is one edge case. Let's say condition is 256. This would overflow into 0 and be equal to
NO
since it is simply a signed char. However, the!
operator returns a C boolean, which is explicitly defined by the C standard to be true for all values other than zero. So theBOOL
would beNO
and thebool
would betrue
-
anticyclope about 11 yearsThe OP wanted to use bool literals and I provide a solution. I don't see any actual reason for this answer to be downvoted, no matter how "pointless" it is, since it is answering the actual question. If you think the question was wrong, downvote the question instead.
-
borrrden about 11 yearsNevermind about that, the above example seems to work itself. The case that bit me is slightly different. For certain cases of BOOL (namely the 8-bit overflow) (flag) and (flag == NO) will both be false.
-
HAS about 11 yearsYou can also use the Objective-C 2.0 notation for accessors for boolValue
-
Lily Ballard about 11 years@borrrden:
!flag
andflag == NO
are, by definition, identical. -
borrrden about 11 years@KevinBallard Yes, you are correct, sorry that I wrote that but I've had trouble with BOOLs before and I thought it was related, but it wasn't. The case I had trouble with was when I expected a
YES
value (and for abool
it would have worked correctly) but instead I got aNO
value. The solution was to either cast tobool
or use !!condition (double not operator that implicitly casts tobool
). I thought for sure it would be related to this but it turns out not to be. -
Ríomhaire over 9 yearsRemember that BOOLs are stored as NSNumbers in Core-Data
-
noamtm over 8 years@anticyclope I didn't personally downvote, I save downvoting for really bad answers. But I supposed you were downvoted because people want the answers here to be "correct" in the sense of "a good way to do it", and not just "technically correct yet somewhat pointless".