Was ist der richtige Weg, um in Objective-C nach einer Nullzeichenfolge zu suchen?


184

Ich habe dies in meiner iPhone App verwendet

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

Es wird jedoch eine Ausnahme ausgelöst, und die Konsole zeigt an, dass der Titel "(null)" lautet.

Also benutze ich das jetzt:

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

Was ist der Unterschied und wie lässt sich am besten feststellen, ob eine Zeichenfolge null ist?


Antworten:


395

Wie andere betont haben, gibt es unter Cocoa / Objective C viele Arten von "null". Eine weitere zu beachtende Sache ist jedoch, dass [title isKindOfClass: [NSNull class]] sinnlos komplex ist, da [NSNull null] als a dokumentiert ist Singleton, sodass Sie nur die Zeigergleichheit überprüfen können. Siehe Themen für Kakao: Verwenden von Null .

Ein guter Test könnte also sein:

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

Beachten Sie, wie Sie die Tatsache nutzen können, dass title.length auch dann, wenn title nil ist, 0 / nil / false zurückgibt, dh in diesem Fall 0, sodass Sie keinen Sonderfall eingeben müssen. Dies ist etwas, an das sich Personen, die mit Objective C noch nicht vertraut sind, nur schwer gewöhnen können, insbesondere wenn sie aus anderen Sprachen kommen, in denen Nachrichten / Methodenaufrufe zum Absturz führen.


Vielen Dank! Ich habe diese Frage jedoch an erster Stelle gestellt, weil ich eine Ausnahme bekam, weil der "Titel" null ist.
Teo Choong Ping

1
Welcher Typ soll der Titel sein? Wenn es sich zum Beispiel um einen NSString handelt, erhalte ich die folgende Warnung: Beim Vergleich der verschiedenen Objective-C-Typen 'struct NSNull *' und 'struct NSString *' fehlt eine Besetzung. Gibt es eine Möglichkeit, dies zu entfernen (ich weiß nicht, ob sich die Dinge seitdem geändert haben) diese Frage wurde gestellt)?
Thebossman

1
Dient mir richtig zum Posten von Code ohne ihn zu kompilieren ;-). title ist vermutlich ein NSString, aber unabhängig vom Titeltyp wird einfach null in den generischen ID-Typ umgewandelt: (id) [NSNull null].
Peter N Lewis

1
@JLT nil und [NSNull null] werden niemals gleich sein. [NSNull null] ist ein Singleton-Objekt, das als Ersatz für nil verwendet werden kann, wenn nil nicht verwendet werden kann (z. B. in einem NSArray- oder NSDictionary-Wert). Ein Anwendungsfall könnte also sein, dass Sie ein NSArray mit optionalen Zeichenfolgen hatten, von denen einige null sein könnten, und Sie verwenden [NSNull null] im Array für die Nullfälle. In der Praxis wird der Test nur selten benötigt, wenn Sie (oder eine von Ihnen verwendete Bibliothek!) [NSNull null] aktiv als Platzhalter verwenden.
Peter N Lewis

1
Ich komme von Flutter hierher und suche nach dem Grund, warum Mapder Wert eines Gegenstands - der nullin Dart steht - nicht mit niloder NULLin Ziel C übereinstimmt . Der Grund war, dass es tatsächlich NUNull nullnicht die NULLNull ist. Vielen Dank, dass Sie @PeterNLewis!
Aleksandar

25

es ist genauso einfach wie

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

Denken Sie daran, dass in Ziel C, wenn das Objekt null ist, 0 als Wert zurückgegeben wird.

Dadurch erhalten Sie sowohl eine Nullzeichenfolge als auch eine Zeichenfolge mit der Länge 0.


49
Dies funktioniert nicht, wenn das Objekt NSNull ist. Dies muss jedoch zuerst explizit überprüft werden.
Jeremy Mack

6
Sie können auch eine Kategorie für NSNull erstellen, damit 0 zur Länge der Nachricht zurückkehrt :)
Mihai Timar

1
Ja, dies wird abstürzen, wenn das Objekt NSNull ist.
Mike Gledhill

Dies wird abstürzen, wenn das Objekt gleich NSNull ist
Joan

1
Zusätzlich zum nicht erkannten NSNull-Selektorproblem wird hier nicht zwischen einem NSString-Zeiger, der null ist, oder einem NSString, der tatsächlich vorhanden ist, aber im Wesentlichen eine leere Zeichenfolge ist, unterschieden. (Zum Beispiel als wörtliches object = @"";oder object = nil;)
KellyTheDude

6

Lesen Sie die folgenden Artikel auf dieser Website:

Ich denke, Ihr Fehler hängt mit etwas anderem zusammen, da Sie die zusätzliche Überprüfung nicht durchführen müssen.

Siehe auch diese verwandte Frage: Richtige Überprüfung der Null-SQLite-Textspalte


Ärgerlicherweise habe ich nicht genug "Punkte", um einen zweiten Hyperlink (auch zu etwas auf dieser Site) hinzuzufügen. Siehe auch: - stackoverflow.com/questions/598396/…
TimM

...erlaube mir. Obwohl Sie in der Lage sein sollten, Ihre eigenen Beiträge von rep 0 zu bearbeiten.
Rog

Danke - das war sehr nett. Als ich meinen ersten Beitrag schrieb, hieß es, dass neue Benutzer nur einen Hyperlink hinzufügen können (was etwas hart erscheint - insbesondere für Querlinks auf dieser Site).
TimM

6

Ich habe festgestellt, dass man etwas Ähnliches tun muss, um es wirklich richtig zu machen

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

Andernfalls kommt es zu seltsamen Situationen, in denen die Kontrolle Ihre Prüfung immer noch umgeht. Ich bin nicht auf einen gestoßen, der es über die isEqualund Längenprüfungen hinaus schafft .


5

Was ist mit all diesen "funktioniert für mich Antworten"? Wir codieren alle in derselben Sprache und die Regeln sind

  1. Stellen Sie sicher, dass die Referenz nicht Null ist
  2. Überprüfen Sie, ob die Länge der Zeichenfolge nicht 0 ist

Das wird für alle funktionieren. Wenn eine bestimmte Lösung nur "für Sie funktioniert", liegt dies nur daran, dass Ihr Anwendungsfluss kein Szenario zulässt, in dem die Referenz null oder die Zeichenfolgenlänge 0 sein kann. Der richtige Weg, dies zu tun, ist die Methode, die behandelt wird was Sie in allen Fällen wollen.


4
Wenn die Referenz nil(Hinweis: nicht "null") lautet , wird beim Senden einer Nachricht wie " length0" (oder der entsprechende 0-Wert für den Rückgabetyp der Methode) ausgegeben. Das ist die Regel der Sprache. nilIn diesem Fall muss nicht separat nachgefragt werden.
Jscs

Ich sagte einfach wegen C ++ - Gewohnheiten null, und wenn Ihr Code Methoden für keine Objekte aufruft, ist Ihr Code wahrscheinlich fehlerhaft. Sie werden feststellen, dass das Aufrufen von Methoden unter NULL / NIL (dasselbe Konzept) in jeder Sprache im Allgemeinen eine schlechte Idee ist. Nur weil Sie mit obj-c so etwas tun können, heißt das nicht, dass Sie einfach keine Objekte herumreichen und versuchen sollten, sie zu verwenden, ohne sich darum zu kümmern.
Nenchev

1
Das Senden der Länge an Null erzeugt 0 - ABER das Senden der Länge an NSNull erzeugt eine Ausnahme.
CD-Stamper

@nenchev Niemand sagt etwas darüber, nur nil-Objekte herumzugeben, aber nach nil zu suchen, dann eine Methode aufzurufen und ihren Rückgabewert zu verwenden, ist IMO schlechter als die Verwendung einer Sprachfunktion, wie sie verwendet werden soll, und die anschließende Überprüfung der Gültigkeit des Rückgabewerts der Methode.
Kevin

@ Kevin Ich bin mir nicht sicher, wie es wirklich schlimmer ist, nur weil es eine Sprachfunktion ist, heißt das nicht, dass es großartig ist. Es wird nicht geprüft, ob die Null einen Codepfad öffnen kann, der zu einem schwer zu verfolgenden Laufzeitfehler führen kann. Normalerweise ist es am besten, zu überprüfen, ob Ihre Eingaben Ihren Erwartungen entsprechen, und entsprechend zu reagieren, wenn dies nicht der Fall ist. Ich persönlich mag die "Funktion" nicht, keine Laufzeitausnahmen zu erhalten, wenn versucht wird, eine Nachricht an ein Null-Objekt zu senden, da es oft einfacher ist, einige Laufzeitfehler zu übersehen.
Nenchev

4

Wenn Sie gegen alle null / leeren Objekte (wie leere Zeichenfolgen oder leere Arrays / Sets) testen möchten, können Sie Folgendes verwenden:

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
Dies prüft nicht wirklich auf Objekt == [NSNull null], was wahrscheinlich sinnvoll wäre.
Peter N Lewis

3

Es gibt zwei Situationen:

Es ist möglich, dass ein Objekt ist [NSNull null]oder es ist unmöglich.
Ihre Anwendung sollte normalerweise nicht verwendet werden. Verwenden [NSNull null];Sie sie nur, wenn Sie ein " null " -Objekt in ein Array einfügen oder als Wörterbuchwert verwenden möchten . Und dann sollten Sie wissen, welche Arrays oder Wörterbücher Nullwerte enthalten können und welche nicht.
Wenn Sie der Meinung sind, dass ein Array niemals [NSNull null]Werte enthält , suchen Sie nicht danach. Wenn es eine gibt [NSNull null], erhalten Sie möglicherweise eine Ausnahme, aber das ist in Ordnung: Objective-C-Ausnahmen weisen auf Programmierfehler hin. Und Sie haben einen Programmierfehler, der durch Ändern von Code behoben werden muss.

Wenn ein Objekt könnte sein [NSNull null], dann überprüfen Sie diese ganz einfach durch die Prüfung
(object == [NSNull null]). Das Aufrufen isEqualoder Überprüfen der Klasse des Objekts ist Unsinn. Es gibt nur ein [NSNull null]Objekt, und der einfache alte C-Operator prüft es auf einfachste und effizienteste Weise.

Wenn Sie ein NSStringObjekt überprüfen , das nicht sein kann [NSNull null](weil Sie wissen, dass es nicht sein kann, [NSNull null]oder weil Sie gerade überprüft haben, dass es sich von unterscheidet [NSNull null], müssen Sie sich fragen, wie Sie eine leere Zeichenfolge behandeln möchten, die eine mit der Länge 0 ist Wenn es sich um eine nullZeichenfolge handelt nil, gibt test (object.length == 0). object.length 0 if zurück object == nil. Dieser Test deckt also keine Objekte und Zeichenfolgen mit der Länge 0 ab. Wenn Sie eine Zeichenfolge mit der Länge 0 behandeln, die sich von einer Nullzeichenfolge unterscheidet, überprüfen Sie einfach, ob object == nil.

Wenn Sie einem Array oder einem Wörterbuch eine Zeichenfolge hinzufügen möchten und die Zeichenfolge möglicherweise Null ist, haben Sie die Wahl, sie nicht hinzuzufügen, durch zu ersetzen @""oder durch zu ersetzen [NSNull null]. Wenn Sie es durch ersetzen, @""verlieren Sie die Fähigkeit, zwischen "no string" und "string of length 0" zu unterscheiden. [NSNull null]Wenn Sie es durch ersetzen , müssen Sie Code schreiben, wenn Sie auf das Array oder Wörterbuch zugreifen, das nach [NSNull null]Objekten sucht.


Sehr lang, aber das ist gut. NSNull sollte nur in Singletons erscheinen! Diese ganze Frage macht keinen Sinn, sagt mir, dass der Codierer etwas nicht richtig gemacht hat, und viele andere haben auch in Zukunft das Handbuch / die gute Code-Praxis nicht gelesen
Stephen J

2

Sie suchen nur nach Null

if(data[@"Bonds"]==nil){
  NSLog(@"it is nil");
}

oder

if ([data[@"Bonds"] isKindOfClass:[NSNull class]]) {
    NSLog(@"it is null");
}

2

MAKRO-Lösung (2020)

Hier ist das Makro, das ich für eine sichere Zeichenfolge verwende, anstatt " (null) " - Zeichenfolge auf einem UILabel zu erhalten, zum Beispiel:

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

Angenommen, Sie haben eine Memberklasse und eine Namenseigenschaft, und der Name ist null:

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

mit Makro:

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

schön und sauber 😊

Erweiterungslösung (2020)

Wenn Sie es vorziehen, in Ihrem Projekt null Null und eine leere Zeichenfolge zu überprüfen, können Sie meine Erweiterungszeile unten verwenden:

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;
}

Beispiel Verwendung

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");
}

Dies würde mit den folgenden Fällen funktionieren, NSString *strOne = @""ODER NSString *strOne = @"StackOverflow"ODER NSString *strOne = [NSNull null]ODER NSString *strOne.


0

Wenn so etwas noch nicht existiert, können Sie eine NSString-Kategorie erstellen:

@interface NSString (TrucBiduleChoseAdditions)

- (BOOL)isEmpty;

@end

@implementation NSString (TrucBiduleChoseAdditions)

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

@end

Das ist wahrscheinlich übertrieben und ich glaube nicht, dass es dieses Problem lösen wird.
Rog

9
Das Selbst == Null ist sinnlos - wenn Selbst Null wäre, hätte Ziel C Sie überhaupt nicht angerufen. [(NSString *) nil isEmpty] würde einfach 0 / nil / false zurückgeben, ohne jemals Ihren Code aufzurufen.
Peter N Lewis

4
Darüber hinaus gibt [(NSString *) nil isEmpty] false zurück. Wenn Sie solche Objective C-Methoden schreiben, ist es besser, sie so zu definieren, dass 0 / nil / false von nil sinnvoll ist. Daher wäre es besser, die Methode als hasCharacters zu schreiben. Beachten Sie, dass die Länge hierfür bereits funktioniert, da Sie if (s.length) an einer beliebigen Stelle verwenden können, wenn (! S.isEmpty) und s.length für den Fall s == nil korrekt 0 zurückgeben.
Peter N Lewis

Dies ist ein schwerer Absturz. Sie haben "isEmpty" für NSString implementiert, aber wenn es tatsächlich NSNull ist, wird isEmpty an NSNull gesendet und stürzt ab, weil es nicht auf diese Nachricht reagiert!
daniel.gindi

0

Was für mich funktioniert ist if ( !myobject )


3
Das funktioniert nicht für Nullobjekte, sondern nur für Nullobjekte. Zum Beispiel ... 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"); }
Rik Smith-Unna

Ähm .. Entschuldigung für die Formatierung, aber der Code wird kompiliert :)
Rik Smith-Unna

0

Die vollständige Überprüfung einer Zeichenfolge auf Nullbedingungen kann wie folgt erfolgen: <\ br>

    if (mystring)
     {
       if ([mystring isEqualToString: @ ""])
        {
          mystring = @ "irgendein String";
        }}
     }}    
    sonst
     {
        // Anweisungen
     }}

0

Ich überprüfe nur Nullzeichenfolgen mit

if ([myString isEqual: [NSNull null]])


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

1
Während dieses Code-Snippet die Frage beantworten kann, bietet es keinen Kontext, um zu erklären, wie oder warum. Fügen Sie ein oder zwei Sätze hinzu, um Ihre Antwort zu erklären.
Brandonscript

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

0

Für Zeichenfolge:

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

}}

Siehe das Bild unten:

Geben Sie hier die Bildbeschreibung ein


0

Für Zeichenfolge:

+ (BOOL) checkStringIsNotEmpty:(NSString*)string {
if (string == nil || string.length == 0) return NO;
return YES;}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.