18

我尝试了一些类似的东西:

if(myString != nil && myString.length) { ... }

并得到:

-[NSNull 长度]:发送到实例的无法识别的选择器

第一个条件失败后Objective-C不会短路吗?

4

4 回答 4

30

Objective-C 确实支持短路评估,就像 C 一样。

似乎在您的示例myString中 isNSNull和 not nil,因此myString != nil是正确的。

NSNull是一个单例,用于表示nil只允许对象的位置,例如在 NSArray 中。

顺便说一句,通常人们会写if (!myString && myString.length == 0). 对比起来nil就很丑了。另外,我会将长度与 0 进行比较。这似乎更清楚。

于 2010-01-13T22:28:53.140 回答
10

Objective-C 是 C 的严格超集。

因为 C 支持短路评估,Objective-C 也支持。

于 2010-01-13T22:28:38.447 回答
3

NSNull 定义为什么?如果它是一个不代表什么的对象,那么它就不会是 nil。换句话说,NSNull 和 nil 是不一样的。

于 2010-01-13T22:28:48.903 回答
0

如果您在某处有 NSNull,您可能正在使用 JSON 解析器或 CoreData。当未设置 CoreData 中的数字时,CoreData 将返回 NSNull - CoreData 中的 NSString 值也可能相同。

同样,您可以在从服务器返回的 JSON 中包含空元素,并且某些解析器会将其作为 NSNull 对象提供给您。所以在这两种情况下,你在使用值时都必须小心,因为你认为是 NSString 或 NSNumber 对象的东西实际上是 NSNull。

一种解决方案是在 NSNull 上定义一个类别,该类别简单地忽略所有发送到对象的未理解消息,如下面的代码所示。然后您的代码将起作用,因为 NSNull.length 将返回 0。您可以在项目的 .pch 文件中包含类似的内容,该文件将包含在项目中的每个文件中。

// NSNull+IgnoreMessages.h
@interface NSNull(IgnoreMessages) 
- (void)forwardInvocation:(NSInvocation *)anInvocation;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
@end

//NSNull+IgnoreMessages.m
#import "NSNull+IgnoreMessages.h"
@implementation NSNull(IgnoreMessages)
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
    if ( [self respondsToSelector:[anInvocation selector]] )
      [anInvocation invokeWithTarget:self];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
    NSMethodSignature *sig=[[NSNull class] instanceMethodSignatureForSelector:aSelector];
        // Just return some meaningless signature
    if(sig==nil)
      sig=[NSMethodSignature signatureWithObjCTypes:"@^v^c"];

    return sig;
}
@end
于 2010-01-14T01:01:46.397 回答