2010-01-13 103 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