Testing for nil in Objective-C -- if(x != nil) vs if(x)
Asked Answered
B

4

74

Most of the examples I found on the net write this:

if(x != nil)
    // ...

Is there any problems with this?

if(x)
    // ...

I tried both in a simple program and couldn't found any difference.

Bodleian answered 30/5, 2011 at 14:47 Comment(0)
M
127

In Objective-C, nil is defined as a value called __DARWIN_NULL, which essentially evaluates to 0 or false in if-statements. Therefore, writing if (x == nil) is the same as writing if (!x) and writing if (x != nil) is equal to if (x) (since comparing to false creates a negation, and comparing to true keeps the condition the same).


You can write your code either way, and it really depends on which you think is more readable. I find if (x) to make more sense, but it depends on your style.

It's like comparing if (someCondition == true) versus if (someCondition).
It all depends on you, and who's going to be reading the code.


Edit: As Yuji correctly mentions, since Objective-C is a superset of C, any condition that evaluates to a value other than 0 is considered to be true, and therefore, if someCondition in the example above were to evaluate to an integer value of, say, -1, comparing it to true would result in false, and the if-statement would not be evaluated. Something to be aware of.

Missi answered 30/5, 2011 at 14:51 Comment(13)
I should add that if(someCondition==true) is discouraged, because in C-derived languages, any value other than 0 can be in principle regarded as a Boolean true value, but due to historical reasons if someCondition is -1 and true is defined as 1 then someCondition==true evaluates to false.Televisor
@Yuji, that is correct. I was trying to imply though, that someCondition evaluates to a boolean, but that is an important warning.Missi
Check the section "working with nil" in the Apple docs: developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/… . As they say, both forms are fine. However, beware that there subtle and treacherous issues if you try to cast an Obj-C reference to BOOL, as described in mikeash.com/pyblog/…Husain
so if x==0; would if(x) and if(x!=nil) behave the same?Syzygy
@Syzygy Yes, they should. nil is essentially equal to 0, so those conditions evaluate to to if (0) and if (0 != 0), both of which are false.Missi
@Syzygy However, you should probably not be comparing an integer to nil (those are disparate types, and even if the compiler allows you to do that, it's just not semantically correct). if (x) and if (x == 0) are both more correct in that context (though you should probably just stick to if (x)).Missi
I ran into an issue where an entity's property compared to nil was not behaving correctly. In my condition, i checked if (entityItem != nil) [array addObject:entityItem]. This was crashing with the complaint of inserting a nil object. In my debug console, if I typed entityItem != nil, it printed <nil>. If I po'd just entityItem, it printed nil. any ideas?Maltreat
@Maltreat I'm assuming that mutableArray should be changed to eventItemIds, correct? What happens if you change the code to read NSString *name = event.name; if (name) { [eventItemIds addObject:name]; }?Missi
@ItaiFerber correct. If I use the above logic, something insane happens. it enters the condition but then crashes saying I can't insert a nil object. I don't know if it's some threading issue, but I've never seen this before.Maltreat
@Maltreat Hmm. Yeah, that's strange. What is the threading model of your application? Where is this code running? (On which thread/queue?) Do you have other threads/queues operating, and what are they doing? (Considering you have a backgroundManagedObjectContext, I assume there must be more than one thread/queue doing work here...)Missi
@Maltreat Additionally, is this happening for the very first event you look at in the loop, or some arbitrary one? Is there a pattern to where this is failing? Does it ever succeed?Missi
It definitely seems like a race condition. It's happening once every 10-20 launches from the background. The code is running on the background thread.Maltreat
@Maltreat Yeah — looks like you've hit upon the issue, though; without substantial additional information, I won't be of much help. Depending on your access to Xcode 8, I'd recommend trying to run it with TSAN; it will likely be able to work out where the race condition is.Missi
M
8

Both

if (x != nil)

and

if ( x )

are equivalent, so pick the variant that in your opinion makes your code more readable for you (and others who will read and support your code)

Midiron answered 30/5, 2011 at 14:52 Comment(0)
R
0

Both are the same and this is a style question and it boils down to whether you prefer:

  1. if (something) { ... }

    versus

  2. if (something != nothing) { ... }

I have always found #1 more clear but #2 is used extensively in documentation and hence the field so it is better to both know both forms and adapt to what a project uses and be stylistically consistent.

Robertroberta answered 28/3, 2015 at 20:31 Comment(0)
T
-2

The best and safe way to check nil is
Make a common method, and add all these null :

+ (NSString *)trimWhiteSpaceAndNewLine:(NSString *)string {
    NSString *stringSource = [NSString stringWithFormat:@"%@",string];
    if ([stringSource isEqualToString:@"(null)"]) {
        stringSource = @"";
        return stringSource;
    }
    if ([stringSource isEqualToString:@"<null>"]) {
        stringSource = @"";
        return stringSource;
    }
    if ([stringSource isEqualToString:@"<nil>"]) {
        stringSource = @"";
        return stringSource;
    }
    if ([stringSource isKindOfClass:[NSNull class]]) {
        stringSource = @"";
        return stringSource;
    }
    if ([stringSource isEqualToString:@""]) {
        stringSource = @"";
        return stringSource;
    }
    if (stringSource == nil) {
        stringSource = @"";
        return stringSource;
    }
    NSString *stringFinal = [stringSource stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    return stringFinal;
}  

And check

NSString *strUuid = [Common trimWhiteSpaceAndNewLine:[dict valueForKeyPath:@"detail.uuid"]];
        if (![strUuid isEqualToString:@""]) {
            // do your stuff
        }
Topee answered 1/8, 2018 at 6:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.