在Objective-C中检查空字符串的正确方法是什么?


184

我在iPhone应用程序中使用了它

if (title == nil) {
    // do something
}

但是它会引发一些异常,并且控制台显示标题为“(null)”。

所以我现在用这个:

if (title == nil || [title isKindOfClass:[NSNull class]]) {
    //do something
}

有什么区别?确定字符串是否为null的最佳方法是什么?


Answers:


395

正如其他人指出的那样,可可/目标C下有许多种“空”。但是要注意的另一点是,[title isKindOfClass:[NSNull class]]毫无意义,因为据记载[NSNull null]是一个单例,这样您就可以检查指针是否相等。请参阅可可主题:使用Null

因此,一个好的测试可能是:

if (title == (id)[NSNull null] || title.length == 0 ) title = @"Something";

注意如何使用这样的事实:即使title为nil,title.length仍将返回0 / nil / false,即在这种情况下为0,因此您不必对其进行特殊处理。这是Objective C的新手很难适应的东西,尤其是来自其他语言的消息/方法调用失败的情况。


谢谢!但是我首先问这个问题,因为我因为“ title”为空而出现异常。
张宗平2009年

1
标题应该是哪种类型?例如,如果它是一个NSString,我将收到以下警告:比较不同的Objective-C类型“ struct NSNull *”和“ struct NSString *”时,是否缺少强制转换?问这个问题)?
thebossman 2010年

1
为我提供发布代码而不编译它的权利;-)。title大概是一个NSString,但是不管title的类型如何,都将null转换为通用ID类型:(id)[NSNull null]。
彼得·刘易斯

1
@JLT nil和[NSNull null]永远不会相同。[NSNull null]是一个单例对象,当不能使用nil时(例如,在NSArray或NSDictionary值中),可以用作nil的代表。因此,用例可能是您有一个包含可选字符串的NSArray,其中一些可能为null,并且您在数组中使用[NSNull null]作为空值。实际上,仅当您(或您使用的库!)主动使用[NSNull null]作为占位符时,才很少需要测试。
Peter N Lewis

1
来自Flutter,寻找为什么Map项目的值(null在Dart中)不对应nil或不符合NULL目标C的原因。原因是它实际上是NUNull null,而不是NULLnull。谢谢@PeterNLewis!
Aleksandar

25

就这么简单

if([object length] >0)
{
  // do something
}

请记住,在目标C中,如果object为null,它将返回0作为值。

这将使您同时得到一个空字符串和一个长度为0的字符串。


49
如果对象为NSNull,则此方法将无效,仍然需要先进行显式检查。
杰里米·麦克

6
您还可以为NSNull设置一个类别,以使长度消息返回0 :)
Mihai Timar,2012年

1
是的,如果对象为NSNull,则会崩溃。
Mike Gledhill

这将崩溃,如果对象是等于NSNull

1
除了无法识别的NSNull选择器问题之外,这不会区分为nil的NSString指针还是实际上存在但实质上为空字符串的NSString。(例如,作为文字object = @"";object = nil;
KellyTheDude

6

请参阅此网站上的以下相关文章:

我认为您的错误与其他情况有关,因为您无需进行额外的检查。

另请参阅以下相关问题:正确检查nil sqlite文本列


烦人我没有足够的“点”添加第二个超链接(即使是在该网站上的东西)也见: - stackoverflow.com/questions/598396/...
蒂姆

...允许我。虽然你应该能够从代表0编辑自己的信息
罗格

谢谢-很好。当我写我的第一篇文章时,它说类似新用户只能添加1个超链接(这似乎有点苛刻-特别是对于本网站中的交叉链接)。
TimM

6

我发现为了真正做到这一点,您最终不得不做类似的事情

if ( ( ![myString isEqual:[NSNull null]] ) && ( [myString length] != 0 ) ) {
}

否则,您会遇到奇怪的情况,即控制仍会绕过检查。我还没有碰到一个通过isEqual和长度检查的项目。


5

这些“对我有用的答案”怎么办?我们都用相同的语言编码,规则是

  1. 确保引用不为零
  2. 检查并确保字符串的长度不为0

那将是对所有人有用的。如果给定的解决方案仅对您“有效”,那是因为您的应用程序流程不允许引用为null或字符串长度为0的情况。执行此操作的正确方法是将处理的方法在任何情况下都想要什么。


4
如果引用为nil(注意:不是“ null”),则发送消息(如length)将产生0(或该方法的返回类型的适当0值)。那是语言的规则。nil在这种情况下,无需单独检查。
jscs 2013年

我之所以说null仅仅是因为C ++习惯,并且如果您的代码正在nil对象上调用方法,那么您的代码很可能被破坏了。您会发现,在任何语言中,对NULL / NIL(相同概念)进行调用的方法通常不是一个好主意。仅仅因为obj-c允许您执行类似操作并不意味着您应该只传递nil个对象并尝试使用它们而无需关心。
nenchev 2014年

1
将长度发送到nil会产生0-但是将长度发送到NSNull会产生异常。
cdstamper 2014年

@nenchev没有人说过仅传递nil个对象,而是检查nil,然后调用一个方法并使用其返回值,这比使用要使用的语言功能并随后检查该方法的返回值的有效性要差。
凯文

@Kevin我不确定它到底有多糟,只是因为它的语言功能并不意味着它很棒。不检查其null是否可以打开代码路径,这可能导致更难跟踪运行时错误。通常最好验证输入是否符合您的期望,如果输入不正确,则做出相应的反应。我个人不喜欢在尝试向nil对象发送消息时不获取运行时异常的“功能”,因为它常常使您更容易错过一些运行时错误。
nenchev '16

4

如果要对所有零/空对象(例如空字符串或空数组/集)进行测试,则可以使用以下命令:

static inline BOOL IsEmpty(id object) {
    return object == nil
        || ([object respondsToSelector:@selector(length)]
        && [(NSData *) object length] == 0)
        || ([object respondsToSelector:@selector(count)]
        && [(NSArray *) object count] == 0);
}

2
这实际上并不检查对象== [NSNull null],这可能很有意义。
Peter N Lewis 2009年

3

有两种情况:

一个对象可能是[NSNull null],或者不可能。
您的应用程序通常不应该[NSNull null];仅在要将“ null ”对象放入数组中或用作字典值时才使用它。然后,您应该知道哪些数组或字典可能包含空值,哪些可能不包含空值。
如果您认为数组永远不包含[NSNull null]值,则不要检查它。如果存在[NSNull null],您可能会遇到一个异常,但这很好:Objective-C异常表明编程错误。而且您遇到了编程错误,需要通过更改一些代码来解决。

如果可能存在对象[NSNull null],则可以通过测试非常简单地进行检查
(object == [NSNull null])。调用isEqual或检查对象的类是胡说八道。只有一个[NSNull null]对象,普通的C运算符以最直接,最有效的方式对其进行检查。

如果检查的NSString对象不能为[NSNull null](因为您知道它不能为对象,[NSNull null]或者因为您刚刚检查了它与的不同[NSNull null],那么您需要问问自己如何处理空字符串,即长度为0的一个字符串。)将其视为null类似字符串nil,然后测试(object.length == 0)。如果object.length返回0,则object == nil此测试覆盖nil个对象和长度为0的字符串object == nil

最后,如果要将字符串添加到数组或字典中,并且该字符串可能为nil,则可以选择不添加字符串,将其替换为@""或将其替换为[NSNull null]。替换为@""意味着您失去了区分“无字符串”和“长度为0的字符串”的能力。替换为[NSNull null]意味着在访问检查[NSNull null]对象的数组或字典时必须编写代码。


很长,但这很好。NSNull仅应出现在单子中!整个问题都没有道理,告诉我编码器没有做正确的事情,将来还会有更多,没有阅读手册/良好的代码实践
Stephen J


2

宏观解决方案(2020)

例如,这是我用于安全字符串的宏,而不是在UILabel上获取“ (空) ”字符串:

#define SafeString(STRING) ([STRING length] == 0 ? @"" : STRING)

假设您有一个成员类和名称属性,名称为nil:

NSLog(@"%@", member.name); // prints (null) on UILabel

与宏:

NSLog(@"%@", SafeString(member.name)); // prints empty string on UILabel

干净漂亮😊

扩展解决方案(2020)

如果您希望在项目中检查nil Null和空字符串,则可以使用下面的扩展名:

NSString + Extension.h

///
/// Checks if giving String is an empty string or a nil object or a Null.
/// @param string string value to check.
///
+ (BOOL)isNullOrEmpty:(NSString*)string;

NSString + Extension.m

+ (BOOL)isNullOrEmpty:(NSString*)string {
    if (string) { // is not Nil
        NSRange range = [string rangeOfString:string];
        BOOL isEmpty = (range.length <= 0 || [string isEqualToString:@" "]);
        BOOL isNull = string == (id)[NSNull null];

        return (isNull || isEmpty);
    }

    return YES;
}

用法示例

if (![NSString isNullOrEmpty:someTitle]) {
    // You can safely use on a Label or even add in an Array for example. Remember: Arrays don't like the nil values!
}



1
@interface NSString (StringFunctions)
- (BOOL) hasCharacters;
@end

@implementation NSString (StringFunctions)
- (BOOL) hasCharacters {
    if(self == (id)[NSNull null]) {
        return NO;
    }else {
        if([self length] == 0) {
            return NO;
        }
    }
    return YES;
}
@end

NSString *strOne = nil;
if([strOne hasCharacters]) {
    NSLog(@"%@",strOne);
}else {
    NSLog(@"String is Empty");
}

这适用于以下情况,NSString *strOne = @""NSString *strOne = @"StackOverflow"OR NSString *strOne = [NSNull null]OR OR NSString *strOne


0

如果这种东西还不存在,则可以创建一个NSString类别:

@interface NSString (TrucBiduleChoseAdditions)

- (BOOL)isEmpty;

@end

@implementation NSString (TrucBiduleChoseAdditions)

- (BOOL)isEmpty {
    return self == nil || [@"" isEqualToString:self];
}

@end

这可能是过大的杀伤力,我认为这不会解决这个问题。
罗格2009年

9
self == nil是没有意义的-如果self为nil,Objective C首先不会打电话给您。[(NSString *)nil isEmpty]只会返回0 / nil / false,而无需调用您的代码。
Peter N Lewis

4
实际上,除此之外,[((NSString *)nil isEmpty]]将返回false。编写此类Objective C方法时,最好对其进行定义,以使nil的0 / nil / false有意义,因此将其编写为hasCharacters会更好。请注意,length已经可以解决此问题,因为您可以在任何要使用if(!s.isEmpty)的地方使用if(s.length),而对于s == nil的情况,s.length将正确返回0。
Peter N Lewis 2009年

这是严重的崩溃。您为NSString实现了“ isEmpty”,但是如果它实际上是NSNull,则isEmpty将被发送到NSNull,并且由于它不响应该消息而崩溃!
daniel.gindi 2012年

0

对我有用的是 if ( !myobject )


3
这不适用于空对象,仅适用于零对象。例如... NSArray *testarray = [NSArray arrayWithObjects:[NSNull null],@"", nil]; NSString *string = [testarray objectAtIndex:0]; NSLog(@"null string value: %@",string); if (!string) { NSLog(@"string evaluates to null"); } if (string && (string==(id)[NSNull null])) { NSLog(@"string does not evaluate to null"); }
里克·史密斯·翁纳

Err ..对格式感到抱歉,但代码会编译:)
Rik Smith-Unna 2012年

0

完整检查字符串是否为空条件可以如下:<\ br>

    如果(mystring)
     {
       if([mystring isEqualToString:@“”])
        {
          mystring = @“一些字符串”;
        }
     }    
    其他
     {
        //声明
     }

0

我只用检查空字符串

如果([myString isEqual:[NSNull null]]


0
if ([linkedStr isEqual:(id)[NSNull null]])
                {
                    _linkedinLbl.text=@"No";
                }else{
                    _linkedinLbl.text=@"Yes";
                }

1
尽管此代码段可以回答问题,但它没有提供任何上下文来解释如何或为什么。考虑添加一两个句子来解释您的答案。
brandonscript

0
if ([strpass isEqual:[NSNull null]] || strpass==nil || [strpass isEqualToString:@"<null>"] || [strpass isEqualToString:@"(null)"] || strpass.length==0 || [strpass isEqualToString:@""])
{
    //string is blank  
}

0

对于字符串:

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

}

请参考下图:

在此处输入图片说明


0

对于字符串:

+ (BOOL) checkStringIsNotEmpty:(NSString*)string {
if (string == nil || string.length == 0) return NO;
return YES;}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.