I tried something along the lines of:
if(myString != nil && myString.length) { ... }
And got:
-[NSNull length]: unrecognized selector sent to instance
Does Objective-C not short-circuit after the first condition fails?
I tried something along the lines of:
if(myString != nil && myString.length) { ... }
And got:
-[NSNull length]: unrecognized selector sent to instance
Does Objective-C not short-circuit after the first condition fails?
Objective-C does support short-circuit evaluation, just like C.
It seems that in your example myString
is NSNull
and not nil
, therefore myString != nil
is true.
NSNull is a singleton and is used to represent nil
where only objects are allowed, for example in an NSArray.
Btw, normally, people write if (!myString && myString.length == 0)
. Comparing to nil
is quite ugly. Also, I'd compare the length to 0. That seems to be more clear.
if (nil == myString)
instead of if (!myString)
you're wrong. nil
is defined as 0 and therefore the two comparisons are exactly the same. –
Soler if(myString.length) {...}
and leave it at that, because if myString is a nil object and you send a length message to it, you will get nil anyway. –
Imbroglio Objective-C is a strict superset of C.
Because C supports short-circuit evaluation, Objective-C does as well.
||
operator is either 1
or 0
, never anything else). –
Santonin What is NSNull defined as? If it is an object that is supposed to represent nothing, than it would not be nil. in other words, NSNull and nil aren't the same.
If you have an NSNull somewhere, you are probably either using a JSON parser or CoreData. When a number in CoreData is not set, CoreData will give you back NSNull - possibly the same goes for NSString values in CoreData too.
Similarly, you can have empty elements in JSON returned from a server and some parsers will give you that as an NSNull object. So in both cases, you have to be careful when you are using values since the thing you thought was an NSString or NSNumber object is really NSNull.
One solution is to define a category on NSNull that simply ignores all non-understood messages sent to the object, as per the code below. Then the code you have would work because NSNull.length would return 0. You can include something like this in your project .pch file, which gets included in every single file in your project.
// NSNull+IgnoreMessages.h
@interface NSNull(IgnoreMessages)
- (void)forwardInvocation:(NSInvocation *)anInvocation;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
@end
//NSNull+IgnoreMessages.m
#import "NSNull+IgnoreMessages.h"
@implementation NSNull(IgnoreMessages)
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if ( [self respondsToSelector:[anInvocation selector]] )
[anInvocation invokeWithTarget:self];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature *sig=[[NSNull class] instanceMethodSignatureForSelector:aSelector];
// Just return some meaningless signature
if(sig==nil)
sig=[NSMethodSignature signatureWithObjCTypes:"@^v^c"];
return sig;
}
@end
NSNull
instead of nil
, your code makes that less likely to happen. In the question's example there's an error message containing NSNull
, you wouldn't see that with your code and if (myString)
would still evaluate to true. –
Soler NSNull
. –
Soler NSMethodSignature *sig=[self methodSignatureForSelector:aSelector];
–
Substratum © 2022 - 2024 — McMap. All rights reserved.