2013-05-17 13 views
13

Di seguito è riportato un blocco di codice, che deve verificare se un dizionario è nullo e, in caso contrario, estrarre l'oggetto corretto. Tuttavia, per qualche motivo, nonostante il fatto che il controllo if non riesca, il codice viene comunque eseguito. C'è qualche stranezza nel modo in cui funziona lo NSNull che non capisco, o si tratta di un bug di Apple?Test di uguaglianza a NSNull

if (svcUser && !(svcUser == (id)[NSNull null])) { 
    return [svcUser objectForKey:@"access_level"]; 
} 

risposta Console:

(lldb) print svcUser && !(svcUser == (id)[NSNull null]) 
(bool) $0 = false 
(lldb) continue 
-[NSNull objectForKey:]: unrecognized selector sent to instance 0x2b51678 
+4

Prova rottura su eccezioni, e assicurarsi che il "selettore di non riconosciuta" viene gettata in cui si pensa che è http://developer.apple.com/library/mac/recipes/xcode_help- breakpoint_navigator/articles/adding_an_exception_breakpoint.html –

+0

Hai mai capito cosa stava succedendo qui? –

+0

La spiegazione definitiva ---> http://nshipster.com/nil/ –

risposta

18

NSNull è una classe. E come con tutte le classi, è necessario utilizzare isEqual:, non == per vedere se due oggetti rappresentano lo stesso valore.

if (svcUser && ![svcUser isEqual:[NSNull null]]) { 
    return [svcUser objectForKey:@"access_level"]; 
} 
+7

Sì, ma '[NSNull null]' è un oggetto singleton, quindi è possibile controllarlo in entrambi i modi, poiché saranno di riferimento uguali. Come si può vedere dall'output della console, la logica 'if' va bene, ma in qualche modo il blocco di codice viene ancora eseguito. – jungziege

+1

Mi sembra di aver sempre usato '==' con successo per 'NSNull'. Il [codice campione] di Apple (http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/NumbersandValues/Articles/Null.html#//apple_ref/doc/uid/TP40005153-SW1) sembra persino approvare questo confronto. –

+2

Ma questo è un dettaglio di implementazione su cui non bisogna contare. Usare 'isEqual:' è migliore e più sicuro che affidarsi a '==' funzionante. Ciò ha bruciato molte persone in passato confrontando i valori letterali di 'NSString'. @jungziege: solo un controllo di integrità, ma sei sicuro al 100% che l'arresto sia nella linea di codice pubblicata e non altrove? – rmaddy

8

È possibile controllare esso utilizzando:

if(![svcUser isKindOfClass:[NSNull class]]){ 
    return [svcUser objectForKey:@"access_level"]; 
} 
+0

perché il voto negativo? – Joshua

+1

Se 'svcUser' è in realtà un oggetto' NSNull', chiamando 'count' su di esso si verificherà un arresto anomalo. Inoltre, l'obiettivo è assicurarsi che sia * non * un oggetto 'NSNull'. E qual è 'nsnull'? – rmaddy

+0

Inoltre, usare '==' per confrontare i due oggetti non è corretto. Devi usare 'isEqual:' per confrontare due oggetti. – rmaddy

26

Semplicemente verificare la presenza di:

svcUser == [NSNull null] 

Questo è l'approccio che Apple cita nel loro docs.

+3

Questo mi ha dato un avvertimento, usa http://stackoverflow.com/a/22825611/62 per sopprimerlo. –

6

L'utilizzo dell'approccio di @ JE42 mi dà l'avviso di Xcode 5.1. Invece cast:

(id)svcUser == [NSNull null]