8

Im trying to set a string to "No Display name if [object objectForKey@"display_name"] is NULL". It crashing with this in the log

2011-06-16 10:58:36.251 BV API[15586:ef03] displayNameType is: NSNull
2011-06-16 10:58:36.251 BV API[15586:ef03] +[NSNull isEqualToString:]: unrecognized selector sent to class 0x1228c40
2011-06-16 10:58:36.253 BV API[15586:ef03] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSNull isEqualToString:]: unrecognized selector sent to class 0x1228c40'
*** First throw call stack:
(0x1198f1c 0x132b52e 0x119bb2b 0x10f3076 0x10f2bb2 0x116d9 0x112ad 0x8b0e17 0x8b9783 0x8b43ae 0x8b9d20 0xb6312b 0x815c35 0xac2e1e 0x8b7583 0x8b771d 0x8b775d 0xc1b5 0x7ed84c 0x7ed7e2 0x89477a 0x894c4a 0x893ee4 0x813002 0x81320a 0x7f960c 0x7ecd52 0x211b8f6 0x116831a 0x10c3d07 0x10c1e93 0x10c1750 0x10c1671 0x211a0c3 0x211a188 0x7eac29 0x1b29 0x1aa5)
terminate called throwing an exceptionsharedlibrary apply-load-rules all
Current language:  auto; currently objective-c

NSString *displayNameType = (NSString *)[[object objectForKey:@"display_name"] class ];
NSLog(@"displayNameType is: %@", displayNameType);

NSString *displayNameString = [NSString stringWithFormat:@"%@", [object objectForKey:@"display_name"]];
displayNameString = [displayNameString uppercaseString];
if ([displayNameType isEqualToString:@"NSNull"]) {
    NSLog(@"dnt is null");
    NSString *displayNameString = @"No Display Name";
    displayNameString = [displayNameString uppercaseString];
}
Vincent Guerci
  • 14,379
  • 4
  • 50
  • 56
Sam Baumgarten
  • 2,231
  • 3
  • 21
  • 46

7 Answers7

41

A cast will not change an object class (type).

You have to manage the case when your value is [NSNull null] with something like :

id displayNameTypeValue = [object objectForKey:@"display_name"];
NSString *displayNameType = @"";
if (displayNameTypeValue != [NSNull null])
   displayNameType = (NSString *)displayNameTypeValue;
Vincent Guerci
  • 14,379
  • 4
  • 50
  • 56
  • I supplied it: `if (displayNameTypeValue != [NSNull null])` or in one line `if ([object objectForKey:@"display_name"] == [NSNull null])` – Vincent Guerci Jun 16 '11 at 18:23
  • thanks @André, I removed my downvote, sorry but got a bit scared that your answer was going to be accepted, and worse, used in a code. :) – Vincent Guerci Jun 16 '11 at 18:44
6

I created a category on NSNull, works well for me:

@interface NSNull (string)

-(BOOL) isEqualToString:(NSString *) compare;

@end

@implementation NSNull (string)

-(BOOL) isEqualToString:(NSString *) compare {    

    if ([compare isKindOfClass:[NSNull class]] || !compare) {
        NSLog(@"NSNull isKindOfClass called!");
        return YES;
    }

    return NO;  
}
@end
Alex L
  • 8,419
  • 6
  • 43
  • 51
Jerry Horton
  • 69
  • 1
  • 1
3

You might want something like this:

NSString *displayNameType = NSStringFromClass([[object objectForKey:@"display_name"] class]);

And btw in your question, it shouldn't read "if it's NULL", but rather "if it's an NSNull instance".

Vincent Guerci
  • 14,379
  • 4
  • 50
  • 56
André Morujão
  • 6,963
  • 6
  • 31
  • 41
  • Good answer? using strings to check an object type?... That's an answer, that works, but seriously... so ugly! > -1 – Vincent Guerci Jun 16 '11 at 18:21
  • 1
    I agree with Vincent G. I would do `foo == [NSNull null]` to test for null, and also do `[foo isKindOfClass:[NSString class]]` to make sure it's really a string if you're parsing something like JSON. – Daniel Dickison Jun 16 '11 at 18:36
  • Personally, I would also go for the [NSNull null] comparison. The code I presented was simply a minimal fix to Sam's original code (which only fixed what was wrong with it, but didn't change the way it worked). – André Morujão Jun 16 '11 at 18:40
2

I'll throw in my answer to clarify a bit. The problem is that the object in the NSDictionary has [NSNull null] value (slightly different to both nil and NULL). The issue comes from some libraries (a particular JSON parser comes to my mind) set the value for some keys with NULL value to [NSNull null]. Why? Because sometimes it is needed to differentiate in a NSDictionary the case when a key is not present from the case when the key has NULL value. In an NSDictionary there is no way of telling, but JSON structures do convey such difference. When you get a a variable that comes from a library or parser that does that the value may be [NSNull null]. NSNull is a singleton thus just checking for equality (pointer equality) is enough. For example I would do:

NSString *value = [object objectForKey:@"display_name"];
if (value && value != [NSNull null]){
   // Here I have the value I expect

   // Do something
}else{
   // The value is null ... don't display
}
fsaint
  • 8,759
  • 3
  • 36
  • 48
1

To my experience, the font may be well missing. If you got the problem, you could check where you set the new font and if it exists.

let font = UIFont.init(name:"YOUR_FONT_NAME", size: 16) -> is it nil or not ?
Nguyen Tan Dat
  • 3,780
  • 1
  • 23
  • 24
QuangLoc
  • 71
  • 1
  • 4
0

I solved this by doing a check against [NSNull null]. The code I used in my app:

_lblBusinessName.text = _business.BusinessName != [NSNull null] ? _business.BusinessName : @"";

However XCode threw some warnings so to get rid of those I casted to an NSObject* type, like this:

_lblBusinessName.text = **(NSObject*)**_business.BusinessName != [NSNull null] ? _business.BusinessName : @"";
kleopatra
  • 51,061
  • 28
  • 99
  • 211
SteveA
  • 31
  • 3
0

Detect whether or not the object is null instead of trying to infer from the class name.

// if you're key may not exist (NSDictionary will return nil... not sure what type
// you are using
if (![object objectForKey:@"display_name"]){
    // ...
}

// or if the value may actually be an NSNull object
if ([[object objectForKey:@"display_name"] == (id)[NSNull null]){
    // ...
}

I haven't tested the second argument, but look here for more about testing null.

Community
  • 1
  • 1
Rob
  • 7,377
  • 7
  • 36
  • 38