6
votes

I really like the new literals in Objective-C. I am wondering if with the new additions there's a better way to compare numbers.

For example, if I want to compare a and b:

a = @1;
b = @2;

Is the only way to compare them like this:

[a intValue] > [b intValue]

Or are there better, more elegant, solutions?

4
If you want, you could write a category adding methods like [a greaterThan: b] and [a equalTo: b]pasawaya
It's possible that compiler rewriting of operators will eventually emerge as an extension of this number literal syntax. @1 already becomes [NSNumber numberWithInt:1] -- there's no reason that @1 > @2 couldn't be allowed and rewritten as [@1 isGreaterThan:@2] (well, no reason aside from possible confusion: "Why can't I do if( 1 > @2 )?").jscs
yea you're right, it would take away low level pointer comparisons...but they could always do something like @1 @>= @2 and then implement greaterThanOrEqualTo in NSNumber, so it would be translated as [@1 greaterThanOrEqualTo:@2]...this way you can keep your pointer arithmetic as well as logical comparisons0xSina
Or they could ditch the whole silly idea of boxing raw types and just go back to using int :-)paxdiablo

4 Answers

13
votes

For equality checks, you can use isEqualToNumber which checks if either the id or content is equal (with the latter using compare):

if ([a isEqualToNumber:b])                  // if a == b

Not sure why they also didn't implement isGreaterThanNumber and isLessThanNumber convenience methods (and possibly >= and <= as well), since the compare method below seems a little clunky.

For inequality checks, just use compare directly (you can also do this for equality as can be seen from the first one below):

if ([a compare:b] == NSOrderedSame)         // if (a == b)
if ([a compare:b] == NSOrderedAscending)    // if (a <  b)
if ([a compare:b] == NSOrderedDescending)   // if (a >  b)

if ([a compare:b] != NSOrderedSame)         // if (a != b)
if ([a compare:b] != NSOrderedAscending)    // if (a >= b)
if ([a compare:b] != NSOrderedSescending)   // if (a <= b)

Details can be found on the NSNumber class documentation page.


Keep in mind there's nothing preventing you from creating your own helper function which would, for example, allow code like:

if (nsnComp1 (a, ">=", b)) ... // returns true/false (yes/no)

or:

if (nsnComp2 (a, b) >= 0)  ... // returns -1/0/+1

even though it's less Objective-C and more C :-) It depends on whether your definition of "elegant" is bound mostly by efficiency or readability. Whether that's preferable to your intValue option is a decision you'll need to make yourself.

7
votes

NSNumber implements -compare: (as do a number of other classes). So you can say

switch ([a compare:b]) {
    case NSOrderedAscending: // a < b
        // blah blah
        break;
    case NSOrderedSame: // a == b
        // blah blah
        break;
    case NSOrderedDescending: // a > b
        // blah blah
        break;
}
0
votes

NSNumber also has an isEqualToNumber:

0
votes

Here is the code snippet to check which works good:

NSLog(@"%d", number1 == number2);
NSLog(@"%d", [number1 isEqual:number2]);
NSLog(@"%d", [number1 isEqualToNumber:number2]);

The output:

1
1
1

Conclusion:

To understand comparison, you need to understand instance allocation. NSNumber internally implements a cache of objects assigned, and maps existing objects to any newly created objects using values. If an existing NSNumber object is found holding value 1, no new NSNumber instance is created.