2013-09-27 12 views
52

Otrzymuję tablicę z wartością pustą. Proszę sprawdzić strukturę mojej tablicy poniżej:Jak mogę sprawdzić, czy obiekt w NSArray jest NSNull?

(
    "< null>" 
) 

Kiedy próbuję uzyskać dostęp do indeksu 0 jego zawieszanie powodu

-[NSNull isEqualToString:]: unrecognized selector sent to instance 0x389cea70 

Obecnie jej upaść z powodu tej tablicy z dziennika awarii:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull isEqualToString:]: unrecognized selector sent to instance 0x389cea70' 
*** First throw call stack: 
(0x2d9fdf53 0x3820a6af 0x2da018e7 0x2da001d3 0x2d94f598 0x1dee57 0x1dfd31 0x302f598d 0x301a03e3 0x3052aeed 0x3016728b 0x301659d3 0x3019ec41 0x3019e5e7 0x30173a25 0x30172221 0x2d9c918b 0x2d9c865b 0x2d9c6e4f 0x2d931ce7 0x2d931acb 0x3262c283 0x301d3a41 0xabb71 0xabaf8) 
libc++abi.dylib: terminating with uncaught exception of type NSException 
+3

proszę umieszczać kod gdzie tablica jest tworzona i obiekty są dodaną. –

+0

wartości są pobierane z plistu – Navi

+0

Wyślij swojego backendowego dewelopera za podanie wartości Null. – GeneCode

Odpowiedz

113
id object = myArray[0];// similar to [myArray objectAtIndex:0] 

if(![object isEqual:[NSNull null]]) 
{ 
    //do something if object is not equals to [NSNull null] 
} 
+2

to nie działa – Navi

+1

jeśli chcesz sprawdzić, czy NSString używa [obiekt isKindOfClass: [klasa NSString]] przed wywołaniem [object isEqualToString:]; –

+0

ok dostałem odpowiedź, teraz dodam tylko dobre wartości do tablicy odrzucającej wszystkie niezbędne nulls..lol dzięki dużo – Navi

28
if (myArray != (id)[NSNull null]) 

OR

if(![myArray isKindOfClass:[NSNull class]]) 
+0

ale tutaj pierwszy indeks tablicy to null nie cała tablica – Navi

+0

ok dostałem odpowiedź, teraz dodam tylko dobre wartości do tablicy odrzucającej wszystkie niezbędne wartości null..lol dziękuję za dużo uproś dla twojego wysiłku – Navi

+2

NSNull to obiekt singleton, więc ty można porównać bezpośrednio do [NSNull null]. – Matt

13

Zbudowanie odpowiedzi Toni stworzyłem makro.

#define isNSNull(value) [value isKindOfClass:[NSNull class]] 

Potem go używać

if (isNSNull(dict[@"key"])) ... 
+4

NSNull jest obiektem pojedynczym, dzięki czemu można porównać bezpośrednio do [NSNull null]. – Matt

+0

Podoba mi się to.Wygląda na to, że powinniśmy mieć kilka z nich dla zwykłych przypadków, takich jak BOOLAsString lub StringFromBOOL –

6

znalazłem kod do pracy z NSNull ma następujące problemy:

  • Wygląda głośny i brzydki.
  • Czasochłonne.
  • Błąd podatny.

Stworzyłem więc następującą kategorię:

@interface NSObject (NSNullUnwrapping) 

/** 
* Unwraps NSNull to nil, if the object is NSNull, otherwise returns the object. 
*/ 
- (id)zz_valueOrNil; 

@end 

z realizacją:

@implementation NSObject (NSNullUnwrapping) 

- (id)zz_valueOrNil 
{ 
    return self; 
} 

@end 

@implementation NSNull (NSNullUnwrapping) 

- (id)zz_valueOrNil 
{ 
    return nil; 
} 

@end 

To działa według następujących zasad:

  • Jeśli kategoria jest zadeklarowana dwukrotnie dla tego samego Class (tj. Instancji typu singleton typu Class), zachowanie jest niezdefiniowane. Jednak metoda zadeklarowana w podklasie może nadpisać metodę kategorii w jej super-klasie.

Pozwala to na bardziej zwięzły kod:

[site setValue:[resultSet[@"main_contact"] zz_valueOrNil] forKey:@"mainContact"]; 

. . w przeciwieństwie do dodatkowych linii do sprawdzenia pod kątem NSNull. Prefiks zz_ wygląda trochę brzydko, ale jest tam dla bezpieczeństwa, aby uniknąć kolizji przestrzeni nazw.

+1

To niezmiernie sprytne. Unikam sprytnego kodu. – gnasher729

+2

@ gnasher729 Ha ha, do ciebie;) –

+0

Problem polega na tym, że nawet jeśli jest sprytny, nie jest jasne, jak to działa dla kogoś, kto nie jest tobą, dopóki nie skomentujesz go mocno, a potem ludzie się do niego przyzwyczają. Każdego cyklu deweloperzy spędzają czas na zastanawianiu się, "Co to jest?", To cykle, w których nie spędzają czasu na rozwiązywaniu problemów. –

7

Awww, chłopaki. To jest proste.

// if no null values have been returned. 
if ([myValue class] == [NSNull class]) { 
    myValue = nil; 
} 

Jestem pewien, że są lepsze odpowiedzi, ale ten działa.

2

W Swift (lub pomost z Objective-C) możliwe jest posiadanie NSNull i nil w tablicy opcji. NSArray s może zawierać tylko obiekty i nigdy nie będzie mieć nil, ale może mieć NSNull. Tablica Swift z typami Any? może jednak zawierać nil.

let myArray: [Any?] = [nil, NSNull()] // [nil, {{NSObject}}], or [nil, <null>] 

Aby sprawdzić przed NSNull użyć is sprawdzić typ obiektu. Proces ten jest taki sam dla Swift tablic i NSArray obiektów:

for obj in myArray { 
    if obj is NSNull { 
     // object is of type NSNull 
    } else { 
     // object is not of type NSNull 
    } 
} 

Można również użyć if let lub guard aby sprawdzić, czy obiekt może być lanego do NSNull:

guard let _ = obj as? NSNull else { 
    // obj is not NSNull 
    continue; 
} 

lub

if let _ = obj as? NSNull { 
    // obj is NSNull 
} 
2

Wiele dobrych i interesujących odpowiedzi już udzielono i (nealry) wszystkie z nich działają.

Podobnie do realizacji (i zabawy):

[NSNull null] udokumentowano powrotu pojedyncza. Dlatego też

if (ob == [NSNull null]) {...} 

działa również dobrze.

Jednakże, ponieważ jest to wyjątek, nie sądzę, że używanie == do porównywania obiektów jest ogólnie dobrym pomysłem. (Gdybym przejrzał twój kod, z pewnością skomentowałbym to).

1

Rozważmy to podejście:

Wariant 1:

NSString *str = array[0]; 

if (str != (id)[NSNull null] && str.length > 0 { 
    // you have a valid string. 
} 

Opcja 2:

NSString *str = array[0]; 
str = str == (id)[NSNull null]? nil : str; 

if (str.length > 0) { 
    // you have a valid string. 
} 
Powiązane problemy