Comparison of NSNumber literals
-
01-07-2021 - |
Question
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?
Solution
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.
OTHER TIPS
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;
}
NSNumber also has an isEqualToNumber:
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.