2010-01-13 105 views
18

我试图沿着线的东西:Objective-C是否使用短路评估?

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

,并得到:

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

是否Objective-C的不短路后的第一个条件失败?

+1

'NSNull'等于'nil'吗? – 2010-01-13 22:28:56

+4

不是。 NSNull和零不是一回事。一点也不。 – bbum 2010-01-13 22:47:58

回答

30

的Objective-C不支持短路评价,就像C.

看来,在你的榜样myStringNSNull而不是nil,因此myString != nil是真实的。

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

顺便说一句,通常,人们写if (!myString && myString.length == 0)。相比nil是相当难看的。另外,我会将长度与0进行比较。这似乎更清楚。

+0

感谢您的提示。我仍然试图使自己符合所有的语法和命名约定。 – kwcto 2010-01-13 22:35:39

+7

我不会说人们通常不会比较零。我已经看到它以相同的频率在两个方向上完成。参数是你可以将它看作'如果myString不是零'而不是'如果不是myString'。 – bobDevil 2010-01-14 01:23:28

+0

其实你是不正确的比较无通过(无==变量)是确保邮件不发送到零对象的正确方法。 – 2011-10-27 20:54:04

10

Objective-C中是C.

的严格的超由于C支持短路评价,Objective-C的不为好。

+1

NString * str = expressionThatReturnsStrOrNil()|| @ “”;不起作用。这是短路评估不起作用。 – 2012-09-12 11:51:36

+1

@PedroMorteRolo:当然可以。你期望什么结果? (请记住'||'运算符的结果不是'1'或'0',绝不是其他)。 – 2012-09-12 12:02:13

+1

你说得对。我错误地认为C具有与Ruby相同的语义。 – 2012-09-13 09:03:38

3

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

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 
+0

这只是等待失败。知道何时处理'NSNull'而不是'nil'很重要,你的代码使得这种情况不太可能发生。在问题的例子中,有一个错误信息包含'NSNull',你不会在你的代码中看到这个错误信息,并且'if(myString)'仍然会评估为true。 – 2010-01-14 11:09:54

+0

那么告诉我,如果你可以发送任何消息给它,它就像nil一样会失败,它仍然会调用NSNull(包括所有的NSObject方法)实际理解的任何消息。 现在它可能会导致错误,因为如果你明确地检查等于零,这将是不正确的。但在大多数编码中,完全是因为nil可以发送任何消息,我只是在类似于(myString.length> 0)的情况下进行测试,在这里可以正常工作。事实上,当一个NSNull滑入你不期望的地方时,这段代码将会阻止你的代码崩溃,所以平衡它是一个稳定增益。 – 2010-01-14 15:41:13

+0

另外,它说的是一个错误消息?这甚至没有任何意义,为什么任何想发回错误消息的地方都会发送NSNull来代替NSString?在实践中,我只见过NSNull从CoreData和一些JSON解析器中走出来,这种测试除了防止非明显的运行时错误外什么都不做。你仍然可以检查NSNull的重要位置。 – 2010-01-14 15:45:34