38

How do you test if an NSString is empty? or all whitespace or nil? with a single method call?

Jacob Relkin
  • 161,348
  • 33
  • 346
  • 320
Yazzmi
  • 1,541
  • 5
  • 18
  • 33
  • posible dup:http://stackoverflow.com/questions/899209/how-do-i-test-if-a-string-is-empty-in-objective-c –  Aug 08 '10 at 21:58

8 Answers8

102

You can try something like this:

@implementation NSString (JRAdditions)

+ (BOOL)isStringEmpty:(NSString *)string {
   if([string length] == 0) { //string is empty or nil
       return YES;
   } 

   if(![[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length]) {
       //string is all whitespace
       return YES;
   }

   return NO;
}

@end

Check out the NSString reference on ADC.

Jacob Relkin
  • 161,348
  • 33
  • 346
  • 320
  • how can i do all that with a single method call? – Yazzmi Aug 08 '10 at 21:48
  • Since he just wrote a function for you, call that. Although I would change it to return YES if it were empty, nil, or had whitespace - and NO if the string had any characters in it (the function as written will return NO if there are characters in the string). – Kendall Helmstetter Gelner Aug 08 '10 at 21:59
  • Yeah `stringCheck` isn't very descriptive; something like `isEmptyString` in a category on `NSString` would be better. ;) – Wevah Aug 08 '10 at 23:25
  • Might want to try `[NSCharacterSet whitespaceAndNewlineCharacterSet]` to include new line characters! – ChrisJF Oct 16 '12 at 20:08
  • 11
    @JacobRelkin, I don't think this quite correct. if the string is nil, then the method will never get called, so if you have: `NSString *str = nil;BOOL isStrEmpty = [str isEmpty];`, then `isStrEmpty` will be `NO`, as `nil` is the same as `NO`. I've used a category like this for a while, and it puzzles me that I haven't thought this before, so I may/likely be wrong. – Jonathan. Nov 25 '12 at 18:38
  • 2
    You could also make it a class category method instead of an instance category method - that way nil could be checked. + (BOOL)isEmptyString:(NSString*)string - [NSString isEmptyString:str] – Josh Bruce Aug 16 '13 at 00:56
  • 2
    or you could have made a method `isPopulated` as opposed to `isEmpty` – Gabriele Petronella Aug 16 '13 at 10:54
  • 3
    I made the very same mistake a while ago. The easier solution (for me at least) was to invert the method's logic and rename it to `isNotEmpty`. I do favor methods that use affirmative naming rather than negative, but in this case... oh, I assume I was too lazy to change every usage. – jweyrich Oct 04 '13 at 19:31
  • @Jonathan. Note that this is a ***class method*** for NSString since it starts with a plus sign "+". If the string is nil, this method will still get called. Ex. `NSString *str = nil; BOOL isStrEmpty = [NSString isStringEmpty:str];` – 262Hz May 30 '15 at 05:33
14

This is what I use, an Extension to NSString:

+ (BOOL)isEmptyString:(NSString *)string;
// Returns YES if the string is nil or equal to @""
{
    // Note that [string length] == 0 can be false when [string isEqualToString:@""] is true, because these are Unicode strings.

    if (((NSNull *) string == [NSNull null]) || (string == nil) ) {
        return YES;
    }
    string = [string stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];

    if ([string isEqualToString:@""]) {
        return YES;
    }

    return NO;  
}
scooter133
  • 1,297
  • 1
  • 15
  • 29
  • 5
    Instead of doing the final compare to @"" you should just see if the [string length] == 0 – p.pad Mar 16 '12 at 16:26
7

I use,

+ (BOOL ) stringIsEmpty:(NSString *) aString {

    if ((NSNull *) aString == [NSNull null]) {
        return YES;
    }

    if (aString == nil) {
        return YES;
    } else if ([aString length] == 0) {
        return YES;
    } else {
        aString = [aString stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
        if ([aString length] == 0) {
            return YES;
        }
    }

    return NO;  
}

+ (BOOL ) stringIsEmpty:(NSString *) aString shouldCleanWhiteSpace:(BOOL)cleanWhileSpace {

    if ((NSNull *) aString == [NSNull null]) {
        return YES;
    }

    if (aString == nil) {
        return YES;
    } else if ([aString length] == 0) {
        return YES;
    } 

    if (cleanWhileSpace) {
        aString = [aString stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]];
        if ([aString length] == 0) {
            return YES;
        }
    }

    return NO;  
}
karim
  • 15,408
  • 7
  • 58
  • 96
4

I hate to throw another log on this exceptionally old fire, but I'm leery about editing someone else's answer - especially when it's the selected answer.

Jacob asked a follow up question: How can I do this with a single method call?

The answer is, by creating a category - which basically extends the functionality of a base Objective-C class - and writing a "shorthand" method for all the other code.

However, technically, a string with white space characters is not empty - it just doesn't contain any visible glyphs (for the last couple of years I've been using a method called isEmptyString: and converted today after reading this question, answer, and comment set).

To create a category go to Option+Click -> New File... (or File -> New -> File... or just command+n) -> choose Objective-C Category. Pick a name for the category (this will help namespace it and reduce possible future conflicts) - choose NSString from the "Category on" drop down - save the file somewhere. (Note: The file will automatically be named NSString+YourCategoryName.h and .m.)

I personally appreciate the self-documenting nature of Objective-C; therefore, I have created the following category method on NSString modifying my original isEmptyString: method and opting for a more aptly declared method (I trust the compiler to compress the code later - maybe a little too much).

Header (.h):

#import <Foundation/Foundation.h>

@interface NSString (YourCategoryName)

/*! Strips the string of white space characters (inlcuding new line characters).
 @param string NSString object to be tested - if passed nil or @"" return will
     be negative
 @return BOOL if modified string length is greater than 0, returns YES; 
 otherwise, returns NO */
+ (BOOL)visibleGlyphsExistInString:(NSString *)string;

@end

Implementation (.m):

@implementation NSString (YourCategoryName)

+ (BOOL)visibleGlyphsExistInString:(NSString *)string
{
    // copying string should ensure retain count does not increase
    // it was a recommendation I saw somewhere (I think on stack),
    // made sense, but not sure if still necessary/recommended with ARC
    NSString *copy = [string copy];

    // assume the string has visible glyphs
    BOOL visibleGlyphsExist = YES;
    if (
        copy == nil
        || copy.length == 0
        || [[copy stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0
        ) {
        // if the string is nil, no visible characters would exist
        // if the string length is 0, no visible characters would exist
        // and, of course, if the length after stripping the white space
        // is 0, the string contains no visible glyphs
        visibleGlyphsExist = NO;

    }
    return visibleGlyphsExist;

}

@end

To call the method be sure to #import the NSString+MyCategoryName.h file into the .h or .m (I prefer the .m for categories) class where you are running this sort of validation and do the following:

NSString* myString = @""; // or nil, or tabs, or spaces, or something else
BOOL hasGlyphs = [NSString visibleGlyphsExistInString:myString];

Hopefully that covers all the bases. I remember when I first started developing for Objective-C the category thing was one of those "huh?" ordeals for me - but now I use them quite a bit to increase reusability.

Edit: And I suppose, technically, if we're stripping characters, this:

[[copy stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0

Is really all that is needed (it should do everything that category method does, including the copy), but I could be wrong on that score.

Josh Bruce
  • 1,002
  • 13
  • 24
  • I've now converted to just that one line instead of the category method in all my code - works as expected; so, no need to create extra code to maintain. – Josh Bruce Aug 20 '13 at 17:47
2

I'm using this define as it works with nil strings as well as empty strings:

#define STR_EMPTY(str)  \
    str.length == 0

Actually now its like this:

#define STR_EMPTY(str)  \
    (![str isKindOfClass:[NSString class]] || str.length == 0)
Cherpak Evgeny
  • 2,659
  • 22
  • 29
1

Maybe you can try something like this:

+ (BOOL)stringIsEmpty:(NSString *)str
{
    return (str == nil) || (([str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]).length == 0);
}
liushuaikobe
  • 2,152
  • 1
  • 23
  • 26
0

Based on the Jacob Relkin answer and Jonathan comment:

@implementation TextUtils

    + (BOOL)isEmpty:(NSString*) string {

        if([string length] == 0 || ![[string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length]) {
            return YES;
        }

        return NO;
    }

    @end
pvllnspk
  • 5,667
  • 12
  • 59
  • 97
0

Should be easier:

if (![[string stringByReplacingOccurencesOfString:@" " withString:@""] length]) { NSLog(@"This string is empty"); }
MCKapur
  • 9,127
  • 9
  • 58
  • 101