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 instance0x3eba63d4'
Am I doing something wrong? Do I need to do it a different way?
The
NULLvalue for Objective-C objects (typeid) isnil.While
NULLis used for C pointers (typevoid *).(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/fromNSArrays e.g.)In Objective-C++:
null(lowercase) ornullptr(C++11 or later) is a null pointer to C++ objects.So to check against
nilyou should either compare againstnil(orNULLrespectively) explicitly:or let ObjC / C do it implicitly for you:
This works as every expression in C (and with Objective-C being a superset thereof) has an implicit boolean value:
Now when checking for
NSNullthis obviously wouldn't work as[NSNull null]returns a pointer to a singleton instance ofNSNull, and notnil, and therefore it is not equal to0x0.So to check against
NSNullone can either use:or (preferred, see comments):
Keep in mind that the latter (utilising a message call) will return
falseifgetCaptionhappens to benil, which, while formally correct, might not be what you expect/want.Hence if one (for whatever reason) needed to check against both
nil/NULLandNSNull, one would have to combine those two checks: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.