isNotEmpty a Short Objective-C Code Snippet
Sunday, July 29th, 2012Today Brent Simmons improved the developer pool of reusable code by posting his code for testing if the value of an object is empty. Most programmers start down this path with NSString where for most purposes an empty string is the same as nil. From there it grows to include NSNull which JSON parser will commonly return, as well as other common objects found in collections such as NSNumber and NSDate and the collections themselves NSDictionary and NSArray.
If you take a look at his code you will notice it’s a function (same as Wil Shipley’s). Because I write almost exclusively Objective-C a function call in my code makes me pause and think. I avoid this by using categories and get to call methods instead of functions. This also avoids the issue of having to write an optimized version of the function to remember to use on NSStrings. With a category you can optimize each individual call for the specific object. So in the hope of improving that shared code pool below is my implementation. Overwhelmingly (97.63% of the time so far) I want to do something with an object when it’s not empty, so my method is reversed. Also isNotEmpty sent to a nil object will result in the correct NO value being returned.
@interface NSString (NSStringExtensions) - (BOOL)isNotEmpty; @end @interface NSNull (NSNullExtensions) - (BOOL)isNotEmpty; @end @interface NSNumber (NSNumberExtensions) - (BOOL)isNotEmpty; @end @interface NSDate (NSDateExtensions) - (BOOL)isNotEmpty; @end @interface NSArray (NSArrayExtensions) - (BOOL)isNotEmpty; @end @interface NSDictionary (NSDictionaryExtensions) - (BOOL)isNotEmpty; @end @implementation NSString (NSStringExtensions) - (BOOL)isNotEmpty { if ([self length] > 0) return YES; return NO; } @end @implementation NSNull (NSNullExtensions) - (BOOL)isNotEmpty { return NO; } @end @implementation NSNumber (NSNumberExtensions) - (BOOL)isNotEmpty { if ([self integerValue] == 0) return NO; return YES; } @end @implementation NSDate (NSDateExtensions) - (BOOL)isNotEmpty { if (self != nil) return YES; return NO; } @end @implementation NSArray (NSArrayExtensions) - (BOOL)isNotEmpty { if ([self count]) return YES; return NO; } @end @implementation NSDictionary (NSDictionaryExtensions) - (BOOL)isNotEmpty { if ([self count]) return YES; return NO; } @end
I wrote these categories in 2003 and haven’t thought about them since then. I have 674 total calls to these functions in my code (how I know the exact percentage on how often I use it). Since I recently discovered the easy to use BNRTimeBlock for testing performance I ran the three implementation 10 million times and came up with the following averages after 10 runs:
Time for == King Kong Conor's isNotEmpty: 0.165795 Brent's RSStringIsEmpty: 0.182188 Wil's isEmpty: 0.860662 Time for == (null) Conor's isNotEmpty: 0.045048 Brent's RSStringIsEmpty: 0.039325 Wil's isEmpty: 0.041882 Time for == @"" Conor's isNotEmpty: 0.167456 Brent's RSStringIsEmpty: 0.186889 Wil's isEmpty: 0.329623 Average: 0.224318
This shows that at .000000022 seconds per call you should be using these easy to read and maintain functions and/or methods all over your Objective-C code. Brent’s longer RSIsEmpty performs similar to Wil’s function as it includes the necessary call to respondsToSelector:. At these speeds I think the RSStringIsEmpty optimization is unnecessary except in the heaviest of loops.
I do believe my version should be renamed isSet or isFull to avoid using “not” in the method name; but although one learns a lot in 10 years, I also have been using isNotEmpty for 10 years.