-
-
Save tonyarnold/2010649 to your computer and use it in GitHub Desktop.
static inline BOOL CBIsEmpty(id obj) { | |
return obj == nil | |
|| (NSNull *)obj == [NSNull null] | |
|| ([obj respondsToSelector:@selector(length)] && [obj length] == 0) | |
|| ([obj respondsToSelector:@selector(count)] && [obj count] == 0); | |
} |
You may wish to try something like this instead for extra type safety/speed. Only works with LLVM/Clang (see http://clang.llvm.org/docs/LanguageExtensions.html#overloading-in-c)
#import <Foundation/Foundation.h>
BOOL __attribute__((overloadable)) CBIsEmpty(NSString *s) { return s == nil || [s length] == 0u; }
BOOL __attribute__((overloadable)) CBIsEmpty(NSArray *a) { return a == nil || [a count] == 0u; }
BOOL __attribute__((overloadable)) CBIsEmpty(NSDictionary *d) { return d == nil || [d count] == 0u; }
BOOL __attribute__((overloadable)) CBIsEmpty(NSSet *s) { return s == nil || [s count] == 0u; }
int main(int argc, const char * argv[])
{
@autoreleasepool {
NSSet *s0 = nil;
NSSet *s1 = [[NSSet alloc] init];
NSMutableSet *s2 = [[NSMutableSet alloc] init];
NSString *st0 = nil;
NSString *st1 = @"";
NSArray *a0 = nil;
NSArray *a1 = [[NSArray alloc] init];
NSMutableArray *a2 = [[NSMutableArray alloc] init];
NSDictionary *d0 = nil;
NSDictionary *d1 = [[NSDictionary alloc] init];
NSMutableDictionary *d2 = [[NSMutableDictionary alloc] init];
assert(CBIsEmpty(s0));
assert(CBIsEmpty(s1));
assert(CBIsEmpty(s2));
assert(CBIsEmpty(st0));
assert(CBIsEmpty(st1));
assert(CBIsEmpty(a0));
assert(CBIsEmpty(a1));
assert(CBIsEmpty(a2));
assert(CBIsEmpty(d0));
assert(CBIsEmpty(d1));
assert(CBIsEmpty(d2));
}
return 0;
}
I like that a lot. There are a lot of specific scenarios I'd handle differently than with the big block of ||
and &&
I have now. I'm using LLVM for everything now as well, so this will work. Thanks, Oliver!
I also added a fall through to your list, @orj (just to catch the unknown returns like dict values, etc) — most of the time I'm really just checking for nil:
BOOL __attribute__((overloadable)) CBIsEmpty(id object) { return object == nil; }
For completeness, how about:
BOOL __attribute__((overloadable)) CBIsEmpty(NSNull *n) { return YES; }
Out of interest @orj, why check for nil first? Wouldn't objc_msgSend do that for you, and faster?
Also why compare to "0u", is that for performance?
Cheers
Yeah, true. msgSend will indeed return 0 if the input is nil. And the 0u is just me being ultra pedantic. It is completely unnecessary.
I also have
CBIsNotEmpty(id obj) { … }
defined that just calls through and inverts the result of this function. Beginning to think it might be overkill — particularly theinline
part…