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?
You can check if [string length] == 0 . This will check if it's a valid but empty string (@"") as well as if it's nil, since calling length on nil will also return 0. There are some very rare NSStrings where this will result in a false negative (saying the string isn't empty, when, for practical purposes, it is).
Any message to nil will return a result which is the equivalent to 0 for the type requested. Since the 0 for a boolean is NO, that is the result. Show activity on this post. Hope it helps.
If you create an object using a method that begins with init, new, copy, or mutableCopy, then you own that object and are responsible for releasing it (or autoreleasing it) when you're done with it. If you create an object using any other method, that object is autoreleased, and you don't need to release it.
A static, plain-text Unicode string object that bridges to String ; use NSString when you need reference semantics or other Foundation-specific behavior.
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 NSArray
s e.g.)In Objective-C++:
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.
You should use
if ([myNSString isEqual:[NSNull null]])
This will check if object myNSString is equal to NSNull object.
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