How to detect if NSString is null?

85,292

Solution 1

The NULL value for Objective-C objects (type id) is nil.

While NULL is used for C pointers (type void *).

(In the end both end up holding the same value (0x0). They differ in type however.)

In Objective-C:

  • nil (all lower-case) is a null pointer to an Objective-C object.
  • Nil (capitalized) is a null pointer to an Objective-C class.
  • NULL (all caps) is a null pointer to anything else (C pointers, that is).
  • [NSNull null] is a singleton for situations where use of nil is not possible (adding/receiving nil to/from NSArrays e.g.)

In Objective-C++:

  • All of the above, plus:
  • null (lowercase) or nullptr (C++11 or later) is a null pointer to C++ objects.

So to check against nil you should either compare against nil (or NULL respectively) explicitly:

if (getCaption == nil) ...

or let ObjC / C do it implicitly for you:

if (!getCaption) ...

This works as every expression in C (and with Objective-C being a superset thereof) has an implicit boolean value:

expression != 0x0 => true
expression == 0x0 => false

Now when checking for NSNull this obviously wouldn't work as [NSNull null] returns a pointer to a singleton instance of NSNull, and not nil, and therefore it is not equal to 0x0.

So to check against NSNull one can either use:

if ((NSNull *)getCaption == [NSNull null]) ...

or (preferred, see comments):

if ([getCaption isKindOfClass:[NSNull class]]) ...

Keep in mind that the latter (utilising a message call) will return false if getCaption happens to be nil, which, while formally correct, might not be what you expect/want.

Hence if one (for whatever reason) needed to check against both nil/NULL and NSNull, one would have to combine those two checks:

if (!getCaption || [getCaption isKindOfClass:[NSNull class]]) ...

For help on forming equivalent positive checks see De Morgan's laws and boolean negation.

Edit: NSHipster.com just published a great article on the subtle differences between nil, null, etc.

Solution 2

You should use

if ([myNSString isEqual:[NSNull null]])

This will check if object myNSString is equal to NSNull object.

Solution 3

Preferred Way to check for the NSNULL is

if(!getCaption || [getCaption isKindOfClass:[NSNull class]])   

Solution 4

if([getCaption class] == [NSNull class])
    ...

You can also do

if([getCaption isKindOfClass:[NSNull class]])
    ...

if you want to be future proof against new subclasses of NSNull.

Solution 5

Just check with this code:

NSString *object;

if(object == nil)

This should work.

Share:
85,292
iosfreak
Author by

iosfreak

Updated on July 08, 2022

Comments

  • iosfreak
    iosfreak almost 2 years

    I have a piece of code that detects if a NSString is NULL, nil, etc. However, it crashes. Here is my code:

    NSArray *resultstwo = [database executeQuery:@"SELECT * FROM processes WHERE ready='yes' LIMIT 0,1"];
    for (NSDictionary *rowtwo in resultstwo) {
    
    NSString *getCaption = [rowtwo valueForKey:@"caption"];
    
    if (getCaption == NULL) {
    theCaption = @"Photo uploaded...";
    } else if (getCaption == nil) {
    theCaption = @"Photo uploaded...";
    } else if ([getCaption isEqualToString:@""]) {
    theCaption = @"Photo uploaded...";
    } else if ([getCaption isEqualToString:@" "]) {
    theCaption = @"Photo uploaded...";
    }
    
    }
    

    And here's the error:

    Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull isEqualToString:]: unrecognized selector sent to instance 0x3eba63d4'

    Am I doing something wrong? Do I need to do it a different way?

    • Admin
      Admin about 13 years
      What’s the data type of rowtwo? Why are you sending it -valueForKey:?
    • Admin
      Admin about 13 years
      I’ll leave this comment for further reference: -valueForKey: is a KVC method. In KVC, [NSNull null] represents the absence of a value for a given key. If you’re using an NSDictionary in a context that doesn’t need KVC, use -objectForKey: instead — it will return nil instead of [NSNull null] when a given key is not present in the dictionary.
    • Admin
      Admin about 13 years
      See this Stack Overflow question for a discussion on the difference between -valueForKey: and -objectForKey:: stackoverflow.com/questions/1062183/…
    • iosfreak
      iosfreak about 13 years
      Getting object from array populated by a database...
    • Admin
      Admin about 13 years
      rowtwo is not an array, otherwise -valueForKey: would return another array. Is it a dictionary?
    • iosfreak
      iosfreak about 13 years
      Please see my edits in how I populated it and used a NSDictionary.
    • Admin
      Admin about 13 years
      It’s a dictionary, then. See my comments #2 and #3.
    • Admin
      Admin about 13 years
      One more note (ha! :-)) — it looks like you’re using some non-Apple class to fetch results from a database query. If a column is NULL (as in SQL NULL), this class has two options when populating a dictionary: either don’t include the corresponding key, or include the corresponding key mapping to an [NSNull null] value. So it is up to this class how to represent SQL NULL values, and your test needs to consider the specifics of this class.
    • Mihir Oza
      Mihir Oza almost 6 years
      You can check my answer stackoverflow.com/a/51626469/3378413
  • Admin
    Admin about 13 years
    True, although the actual error is that [rowtwo valueForKey:@"caption"] is returning an NSNull instance instead of an NSString instance.
  • Regexident
    Regexident about 13 years
    @Bavarious: See last line in answer.
  • Caleb
    Caleb about 13 years
    Since NSNull is a singleton, you could actually compare pointers directly: if (getCaption == [NSNull null])...
  • jscs
    jscs about 13 years
    @phpnerd211: this probably doesn't solve your real problem, though -- see Bavarious's comments attached to the question.
  • iosfreak
    iosfreak about 13 years
    He was mistaken. I use this method all over my app and it functions properly -- see my edits in my code on how I populated the array, etc.
  • Admin
    Admin about 13 years
    @phpnerd211 I advise you not to use -valueForKey: because it serves a different purpose. If you’re using NSDictionary, use its -[NSDictionary objectForKey:] method. If you want to learn more about KVC and -valueForKey:, there are a couple of guides on Apple’s web site.
  • Dustin
    Dustin over 12 years
    getCaption == [NSNull null] is a bad idea to use. It's better to do [getCaption class] == [NSNull class]. You're free to create new instances of NSNull and some JSON parsers do make new ones instead of using the singleton.
  • Dustin
    Dustin over 12 years
    But comparing against the singleton is a bad idea! Don't do it =X. [NSNull null] may be a singleton but NSNull is a class like any other.
  • Patrick
    Patrick almost 12 years
    I found that using '(getCaption == [NSNull null])' worked fine but got a comparison warning so I changed it to 'if (getCaption == (id)[NSNull null])'
  • Evan R
    Evan R over 9 years
    Of all the answers on this page, only your top answer is working for me in Xcode 6.1, using an NSString property called body that's null. Debugger output: _body NSString * class name = NSNull 0x0000000107279ce0 and Printing description of ad->_body: <null>
  • stackOverFlew
    stackOverFlew almost 8 years
    I had to check for NSNull as well, strange. Seems my NSString was set
  • Bosoud
    Bosoud over 5 years
    perfect answer , Clear
  • Genevios
    Genevios over 4 years
    Bless you! Perfect answer!