字符串isNullOrEmpty作为类别

时间:2012-03-14 19:57:31

标签: iphone objective-c ios null objective-c-category

我正在尝试创建一个检查null / nil / empty字符串的方法,并且我试图让它作为一个类别运行但没有运气。

我正在使用此代码,基于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

然而,当我尝试使用它时,这就是我得到的:

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

这令我感到困惑,我只能假设iOS5 / ARC的某些组合导致nil对象被强制转换为空字符串/指针。调试器将字符串显示为0x0,但是当我使用isNullOrEmpty方法时,我得到了错误。

9 个答案:

答案 0 :(得分:5)

return self == nil

这种情况永远不会发生。如果您尝试将isNullOrEmpty(或任何其他消息)发送到nil,则不会发生任何事情(objc_msgSend(),负责发送消息的功能,会将nil个接收方检查为一个它做的第一件事和中止)。

self == (id)[NSNull null]

这也永远不会发生。如果您将isNullOrEmpty发送给NSNull实例的对象,则不会调用此方法(NSString上的方法)。相反,NSNull的版本(可能不存在)将是。

同样,([self respondsToSelector:@selector(count)] && [(NSArray *) self count])永远不会发生。如果对象 NSArray,那么isNullOrEmpty将永远无法运行,因为它再次是NSString的方法。

相应地,[(NSData *) self length]没有按照您的想法行事。 NSString个实例会回复length,但是将对象转换为NSData不会使用该方法的NSData版本 - 它仍然最终成为NSString的{​​{1}}版本,因为对象实际上是一个length(仅在编译时进行投射;它不能改变任何东西在运行时间。)

NSString

此处您似乎再次检查[self isEqualToString:@"(null)"] ,但您被nil在打印NSLog时选择的表示误导了:

nil

这会在控制台中显示NSLog(@"%@", nil); ,但这并不意味着对象本身就是包含这些字符的字符串。 (null)只需选择要显示NSLog。*

的字符串

你正在做的一些事情要求将它放在nil的类别中,这样即使对象不是{{},实际上也会调用 方法。 1}}。

要检查只包含空格的字符串,只需在修剪空格后与空字符串NSObject进行比较:

NSString

*更好的是,@""显示NSString * trimmedSelf = [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; // Then either: [trimmedSelf isEqualToString:@""]; // Or: ([trimmedSelf length] == 0); (括号而不是括号),在遇到NSLog(@"%@", [NSNull null]);的前几次时会让人感到困惑。

答案 1 :(得分:1)

另一种方法可以是定义一个简单的宏。

#define NSStringIsNullOrEmpty(str) ((str==nil) || [(str) isEqualToString:@""])

简单有效。如果您不喜欢宏,可以随时将其转换为函数调用,而不会影响代码的其余部分。

- 更新:

@Bryan提出了一个很好的观点。内联函数是一个很好的方法。这是一个更新的宏,它只会评估str一次。

#define NSStringIsNullOrEmpty(str) ({ NSString *_str=(str); ((tmp==nil) || [tmp isEqualToString:@""]);})

答案 2 :(得分:0)

在Objective-C中,向nil发送消息将始终返回0(或NO,归零结构,NULL等,具体取决于声明的返回类型)。当您将isNullOrEmpty发送到isNullOrEmpty时,实际上不会调用您编写的nil方法。有关详细信息,请参阅Sending a message to nil?的已接听答案。

也许您可以将方法更改为isNotNullOrEmpty。然后,将isNotNullOrEmpty发送到nil时,返回值为0会有意义。

答案 3 :(得分:0)

您不是在调用您的方法,而是向nil发送消息

答案 4 :(得分:0)

这是预期的行为。毕竟,您正在向nil发送消息。所以它返回nil(或其他0值)。哪个短路为假,以便在下面显示的情况下打印'0':

NSLog([s1 isNullOrEmpty] ? @"1":@"0"); // prints 0
NSLog([(NSString*)nil isNullOrEmpty] ? @"1":@"0"); // prints 0

您甚至可以通过在新类别方法中设置断点来确认没有为这些情况调用此消息。

答案 5 :(得分:0)

正如其他人所说,调用[nil isNullOrEmpty];实际上不会运行你的方法。 nil对象就是:自己清空。

作为一种解决方案,我想说这不是因为你使用的是面向对象的语言,你绝不能使用函数。

BOOL IsStringNilOrEmpty(NSString*)str
{
    return str == nil ||
        str == null ||
        [@"" isEqualToString:str] ||
        [[str stringByReplacingOccurrencesOfString:@" " withString:@""] length] == 0||
        [str isEqualToString:@"(null)"]
        || ([str respondsToSelector:@selector(length)] && [(NSData *) str length] == 0)
        || ([str respondsToSelector:@selector(count)] && [(NSArray *) str count] == 0)
        || [[str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] == 0;   
}

答案 6 :(得分:0)

实际上我只是通过转动来解决这个问题

-(BOOL) isNotNullOrWhiteSpace
{
        return [self length] != 0 && [[self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length] != 0;
}

所以不是isNullOrWhiteSpace而是isNotNullOrWhiteSpace。

答案 7 :(得分:0)

这是我检查null / empty

的方法

- (的NSString *)NULLInputinitWithString:(的NSString *)InputString {

if( (InputString == nil) ||(InputString ==(NSString*)[NSNull null])||([InputString isEqual:nil])||([InputString length] == 0)||([InputString isEqualToString:@""])||([InputString isEqualToString:@"(NULL)"])||([InputString isEqualToString:@"<NULL>"])||([InputString isEqualToString:@"<null>"]||([InputString isEqualToString:@"(null)"])||([InputString isEqualToString:@"NULL"]) ||([InputString isEqualToString:@"null"])))

    return @"";
else
    return InputString ;

}

答案 8 :(得分:-1)

您是否考虑过在扩展NSString的类别上创建类方法?

的NSString + NSStringExtensions.h

#import <Foundation/Foundation.h>

@interface NSString(NSStringExtensions)
+(BOOL)isNilOrEmpty:(NSString*)string;
@end

的NSString + NSStringExtensions.m

#import "NSString+NSStringExtensions.h"

@implementation NSString(NSStringExtensions)

+(BOOL)isNilOrEmpty:(NSString*)string
{
    if (nil == string)
    {
        return YES;
    }
    if (string.length == 0)
    {
        return YES;
    }
    return NO;
}

@end

然后你就这样使用它:

#import "NSString+NSStringExtensions.h"
...
NSLog([NSString isNilOrEmpty:@""] ? @"1":@"0");