I’m trying to create a method which checks for a null/nil/empty string, and I’m trying to get it working as a category but having no luck.
I’m using this code, based on answers in this topic:
@implementation NSString (NSStringExtension)
- (BOOL)isNullOrEmpty {
return self == nil ||
self == (id)[NSNull null] ||
[@"" isEqualToString:self] ||
[[self stringByReplacingOccurrencesOfString:@" " withString:@""] length] == 0||
[self isEqualToString:@"(null)"]
|| ([self respondsToSelector:@selector(length)] && [(NSData *) self length] == 0)
|| ([self respondsToSelector:@selector(count)] && [(NSArray *) self count] == 0)
|| [[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0;
}
@end
Yet when I try to use this this is what I get:
NSLog([@"" isNullOrEmpty] ? @"1":@"0"); // prints 1
NSString *s1 = nil;
NSLog([s1 isNullOrEmpty] ? @"1":@"0"); // prints 0
NSLog([args.itemName isNullOrEmpty] ? @"1":@"0"); // prints 0
NSLog([(NSString*)nil isNullOrEmpty] ? @"1":@"0"); // prints 0
This is baffling me, and I can only assume that some combination of iOS5/ARC is causing the nil object to be coerced to a blank string/pointer. The debugger shows the string as 0x0, yet when I use my isNullOrEmpty method, I get false.
This can never happen. If you try to send
isNullOrEmpty(or any other message) tonil, nothing happens (objc_msgSend(), the function responsible for message dispatch, checks for anilreciever as one of the first things it does and aborts).This will also never happen. If you send
isNullOrEmptyto an object that’s an instance ofNSNull, your method here, which is a method onNSString, will not be called. Instead,NSNull‘s version (which probably doesn’t exist) will be.Likewise,
([self respondsToSelector:@selector(count)] && [(NSArray *) self count])is never going to happen. If the object is anNSArray, thenisNullOrEmptywill never run, because, again, it’s a method ofNSString.Correspondingly,
[(NSData *) self length]doesn’t do what you think it does.NSStringinstances do respond tolength, but casting the object toNSDatadoesn’t use theNSDataversion of the method — it still ends up as theNSStringversion oflength, because the object actually is anNSString(casting only happens at compile-time; it can’t change anything at run-time).Here you appear to be checking for
nilagain, but you are being misled by the representation thatNSLogchooses when it printsnil:This displays
(null)in the console, but that doesn’t mean that the object itself is a string with those characters.NSLogjust chooses that string to display fornil.*Several of the things you are doing would require this to be in a category on
NSObject, so that the method would in fact be called even if the object was not anNSString.To check for a string consisting only of whitespace, all you need is the comparison to the empty string
@""after trimming whitespace:*And even better, doing
NSLog(@"%@", [NSNull null]);displays<null>(angle brackets instead of parentheses), wonderfully confusing the first few times you encounterNSNull.