23

I have a JSON parser in my app, and I load the value into a detailDataSourceDict variable. When I try to get the valueForKey of the array and try to compare it to 0, it never works...

Here's my code:

if (indexPath.row == 1) {
    NSNumber *rating = [detailDataSourceDict valueForKey:@"rating"];
    NSLog(@"Rating:  %@",rating);
    if (rating == 0) {
        cell.detailTextLabel.text = @"This sheet has not yet been rated.";
    }
    else {
        cell.detailTextLabel.text = [NSString stringWithFormat:@"This sheet has a %@ star rating.",rating];
    }
    cell.textLabel.text = @"Rating";


}

I see in my JSON feed that "rating":"0", but when the rating is 0, it shows "This sheet has a 0 star rating.", instead of "This sheet has not yet been rated."

Any suggestions? Thanks.

1789040
  • 569
  • 2
  • 6
  • 17

4 Answers4

60

NSNumber *rating is an object. 0 is a primitive type. Primitive types can be compared with ==. Objects cannot; they need to be compared for equality using isEqual:.

Thus replace this:

rating == 0

with:

[rating isEqual:@0]

(@0 being a NSNumber literal)

or alternatively:

rating.integerValue == 0

The reason why your wrong code even compiles is that 0 is equal to 0x0 which in turn is equal to nil (kind of, sparing the details). So, your current code would be equivalent to this:

rating == nil
Ky -
  • 30,724
  • 51
  • 192
  • 308
Regexident
  • 29,441
  • 10
  • 93
  • 100
  • Thank you for your quick replies... I will accept the answer which works best for me when Stack Overflow lets me... – 1789040 Nov 17 '12 at 15:45
  • 2
    This is correct, the funny thing is Xcode COULD & SHOULD present a warning in such cases. – Pedro Borges Sep 16 '14 at 11:47
  • If you are comparing objects with integers, why does xcode not throw an error? –  Jan 12 '16 at 23:38
  • 1
    Because ObjC (and C, which ObjC is based on) casts pointers to integers implicitly here. Bugs like these are one of the many reasons Swift has no implicit casts. As annoying as that might be sometimes (CGFloat, anybody?), correct choice overall. ;) – Regexident Jan 13 '16 at 15:21
  • I came here looking for a way to check if `NSNumber` is `0`, after worrying about `integerValue`'s behaviour outside of range. I think you probably want the `[rating isEqual:@0]` option. – Steven Fisher Jun 07 '17 at 18:13
4

rating is a pointer to an NSNumber object, if you compare with == 0, you'll be comparing the pointer only.

If you want to compare the value with 0, you'll have to get the actual value using intValue, try;

if ([rating intValue] == 0) {
Joachim Isaksson
  • 176,943
  • 25
  • 281
  • 294
  • Thank you for your quick replies... I will accept the answer which works best for me when Stack Overflow lets me... – 1789040 Nov 17 '12 at 15:45
4

NSNumber is an object and you have to access it's value with the value accessors.

[NSNumber intValue];

See "Accessing Numeric Values" @:

https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/Reference/Reference.html

Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281
bryanmac
  • 38,941
  • 11
  • 91
  • 99
  • Thank you for your quick replies... I will accept the answer which works best for me when Stack Overflow lets me... – 1789040 Nov 17 '12 at 15:46
3

You want to change it from:

if (rating == 0) {

To

if ([rating intValue] == 0) {
sampson-chen
  • 45,805
  • 12
  • 84
  • 81