2010-01-13 5 views
18

habe ich versucht, etwas entlang der Linien von:Verwendet Objective-C eine Kurzschlussauswertung?

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

Und bekam:

- [NSNull Länge]: Unbekannter Selektor zum Beispiel

Does Objective-C nicht kurz nach dem ersten

gesendet Zustand versagt?

+1

Ist 'NSNull' gleich' nil'? –

+4

Nein. NSNull und Nil sind nicht dasselbe. Ganz und gar nicht. – bbum

Antwort

30

Objective-C hat Kurzauswertung unterstützen, ebenso wie C.

Es scheint, dass in Ihrem Beispiel myString ist NSNull und nicht nil daher myString != nil wahr ist.

NSNull ist ein Singleton und wird verwendet, um nil zu repräsentieren, wo nur Objekte erlaubt sind, zum Beispiel in einem NSArray.

Btw, normalerweise schreiben Leute if (!myString && myString.length == 0). Vergleichen mit nil ist ziemlich hässlich. Außerdem würde ich die Länge mit 0 vergleichen. Das scheint klarer zu sein.

+0

Danke für den Tipp. Ich versuche immer noch, mich an alle Syntax- und Namenskonventionen anzupassen. – kwcto

+7

Ich würde nicht sagen, dass Leute "normalerweise" nicht mit Null vergleichen. Ich habe es in beiden Richtungen mit gleicher Häufigkeit gesehen. Das Argument ist, dass Sie es lesen können, wenn myString nicht nil ist, im Gegensatz zu "if not myString". – bobDevil

+0

Eigentlich sind Sie falsch im Vergleich zu Null via (nil == Variable) ist der richtige Weg, um sicherzustellen, dass eine Nachricht nicht an ein Nullobjekt gesendet wird. –

10

Objective-C ist eine strenge Superset von C.

Da C als auch Kurzschlussbewertung, Objective-C nicht unterstützt.

+1

NString * str = AusdruckThatReturnSStrOrNil() || @ ""; funktioniert nicht. Dies ist eine Kurzschlussauswertung, die nicht funktioniert. –

+1

@PedroMorteRolo: Natürlich funktioniert es. Welches Ergebnis erwartest du? (Denken Sie daran, dass das Ergebnis des '||' -Operators entweder '1' oder '0' ist, niemals etwas anderes). –

+1

Sie haben Recht. Ich fiel in die Illusion, dass C dieselbe Semantik wie Ruby hatte. –

3

Worin wird NSNull definiert? Wenn es ein Objekt ist, das nichts darstellen soll, dann wäre es nicht null. Mit anderen Worten, NSNull und nil sind nicht gleich.

0

Wenn Sie irgendwo einen NSNull haben, verwenden Sie wahrscheinlich entweder einen JSON-Parser oder CoreData. Wenn eine Zahl in CoreData nicht gesetzt ist, gibt CoreData Ihnen NSNull zurück - möglicherweise dasselbe gilt auch für NSString-Werte in CoreData.

In ähnlicher Weise können Sie leere Elemente in JSON von einem Server zurückgegeben und einige Parser geben Ihnen das als ein NSNull-Objekt. In beiden Fällen müssen Sie vorsichtig sein, wenn Sie Werte verwenden, da es sich bei der Sache, die Sie für ein NSString- oder NSNumber-Objekt hielten, tatsächlich um NSNull handelt.

Eine Lösung besteht darin, eine Kategorie in NSNull zu definieren, die einfach alle nicht verstandenen Nachrichten ignoriert, die an das Objekt gesendet werden, wie im folgenden Code beschrieben. Dann würde der Code, den Sie haben, funktionieren, weil NSNull.length 0 zurückgibt. Sie können so etwas in Ihre Projektdatei .pch einfügen, die in jeder einzelnen Datei in Ihrem Projekt enthalten ist.

// 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

Das wartet nur um zu scheitern. Es ist wichtig zu wissen, wann Sie mit 'NSNull' anstelle von' nil' zu tun haben, Ihr Code macht dies weniger wahrscheinlich. Im Beispiel der Frage gibt es eine Fehlermeldung, die 'NSNull' enthält, Sie würden das nicht mit Ihrem Code sehen und' if (myString) 'würde immer noch als wahr ausgewertet werden. –

+0

Also sagen Sie mir, wie kann es scheitern, wenn Sie eine Nachricht an es senden können, genau wie nil ... und es wird immer noch auf jede Nachricht aufrufen, die tatsächlich von NSNull verstanden wird (einschließlich aller NSObject-Methoden). Nun kann es Fehler verursachen, wenn Sie ausdrücklich auf Äquivalenz zu nil überprüfen, dass das nicht wahr sein wird. Aber in den meisten Codierungen, genau weil nil jede Nachricht gesendet werden kann, die ich gerade gegen etwas wie (myString.length> 0) testen, die hier gut funktioniert. In der Tat wird dieser Code mögliche Abstürze in Ihrem Code verhindern, wenn ein NSNull reinrutscht, wo Sie es nicht erwartet haben, auf der Balance ist es also ein Stabilitätsgewinn. –

+0

Auch, wo heißt es eine Fehlermeldung? Das macht überhaupt keinen Sinn, warum würde irgendetwas, das eine Fehlermeldung zurücksenden möchte, jemals NSNull anstelle eines NSString senden? In der Praxis habe ich nur gesehen, dass NSNull aus CoreData und einigen JSON-Parsern herauskommt, und zwar auf eine Weise, bei der dieser Test nichts anderes tut, als nicht offensichtliche Laufzeitfehler zu verhindern. Sie können immer noch nach NSNull suchen, wo es wichtig ist. –

Verwandte Themen