2010-11-20 19 views
5

Prima di tutto Confesso la mia ignoranza, ho imparato tutto ciò che so su Objective-C nei pochi mesi in cui ho lavorato al mio progetto. Trovo anche estremamente frustrante il modo in cui Objective-C sembra complicare ciò che sarebbe semplice in qualsiasi altra lingua con cui ho lavorato. Questa domanda è un caso in questione ...Come verificare il valore nullo in NSNumber

Nella prima esecuzione la mia app scarica un gruppo di JSON che utilizza per compilare un negozio CoreData. Io uso una libreria Obj-C/JSON (CJSONDeserializer) per convertire il JSON in NSArrays. Nel download JSON per un'entità CoreData è presente un campo contenente un numero ("show_id":2) che identifica il campo correlato in un'altra entità se esiste uno o null ("show_id":null) in caso contrario. Nel trattamento quel campo assegno a un NSNumber utilizzando ...

NSNumber *shoIndex = [[item objectForKey:typeKey] objectForKey:@"show_id"]; 

Allora provo a controllare che ho un numero valido prima di tentare di recuperare & link record correlato in modo da non fare l'elaborazione sprechi dove ci non è un record correlato.

Interrogazione shoIndex con ...

NSLog(@"shoIndex: %i, %@, %@", shoIndex, shoIndex, [shoIndex description]); 

Dà ...

shoIndex: 19590600, <null>, <null> 

in cui il valore JSON era null & ...

shoIndex: 228300880, 51, 51 

altrimenti.

Finora l'unico controllo di successo che ho fatto è con ...

if (![[shoIndex description] isEqualToString:@"<null>"]) { 

Qualcuno può suggerire un modo migliore?

Aggiornamento ...

Guardando un altro modo shoIndex viene assegnato come NSNumber che a volte contiene un valore @"<null>"NSString. Obj-C ha qualcosa come un operatore isa che potrei usare per verificare il tipo di contenuto di shoIndex?

TIA, Pedro.

+0

Cosa ti fa pensare che l'oggetto è un'istanza di 'NSNumber'? – jlehr

risposta

10

Usa [shoObject class] per ottenere la classe di un oggetto; così, per testare shoObject 's di classe, si usa

[shoObject isKindOfClass:[NSString class]]; 

Dopo aver ordinato che cosa marcatori definiscono una stringa vuota o NSNumber, è possibile creare una macro. Faccio ciò mantenendo una macro IsEmpty in un file chiamato CommonMacros.h. Ecco il codice:

//Thanks Wil 
//http://wilshipley.com/blog/2005/10/pimp-my-code-interlude-free-code.html 

static inline BOOL IsEmpty(id thing) { 
    return thing == nil 
    || ([thing isEqual:[NSNull null]]) //JS addition for coredata 
    || ([thing respondsToSelector:@selector(length)] 
     && [(NSData *)thing length] == 0) 
    || ([thing respondsToSelector:@selector(count)] 
     && [(NSArray *)thing count] == 0); 
} 

Quindi, dopo l'importazione di CommonMacros.h, è possibile chiamare la funzione in questo modo:

if (IsEmpty(shotIndex)) { 
    //do stuff 
} 

Questo dovrebbe prendersi cura di questo problema, e lavorerà anche sulle stringhe, array, ecc, come si può vedere dal codice. Grazie a Wil Shipley!

+0

Grazie Wil, è una sorpresa. Guardando l'URL che hai dato lì, penso che tu mi abbia già aiutato in altri modi :) – Pedro

+0

Ho parlato troppo presto. Voglio fare cose se shoIndex non è vuoto, quindi ho provato! IsEmpty (shoIndex) e il mio NSNumber vola dritto anche se. – Pedro

+0

Hmm, strano, è un peccato. Ti suggerisco di aggiungere questo isEqualToString: @ "" test al codice IsEmpty, ma ovviamente schivare quella rotta è il motivo per cui hai posto questa domanda in primo luogo. –

-1

In Objective-c, è nil non null. Quindi:

if (shotIndex != nil) { 
    // its not nil 
} 
+2

Questo è esattamente ciò che ho provato per la prima volta e non ha funzionato. Dove vedi nella mia domanda è ciò che NSLog fornisce per NSNumber dove l'elemento JSON era nullo. – Pedro

+0

Questo è JSON. Se shotIndex non fosse presente nei dati JSON, sarebbe nullo. Tuttavia, come ha detto Pedro, lo shotIndex era presente con un valore null e i parser JSON ti daranno un valore di [NSNull null], non nullo. L'invio della maggior parte dei messaggi a [NSNull null] si interromperà, quindi questa è una differenza importante. – gnasher729

0

In alcuni casi, come chiavi mancanti in NSUserDefaults, si ottiene il letterale @ "" come stringa vuota.

Ecco il mio controllo sicuro per un NSNumber.

Nota l'assegno al fatto che è un NSNumber si verifica in primo luogo perché NSNumber non capisce isEqualToString

 id savedPin = [[NSUserDefaults standardUserDefaults] valueForKey:@"blah"]; // don't assume is created so don't type as NSNumber* 
     if (![savedPin isKindOfClass:[NSNumber class]] && [savedPin isEqualToString:@""]) { 
Problemi correlati