7
votes

Now that we have NSNumber literals with compiler support in Objective-C, is there a preferred way to compare an NSNumber to a known integer value?

The old way is [myNumber integerValue] == 5

Now we can do [myNumber isEqualToNumber:@5] or even [myNumber isEqualToNumber:@(someVariable)].

Is there an advantage to the isEqualToNumber: method, or should we stick with integerValue unless the value to compare to is already an NSNumber?

One advantage I can see is if someVariable changes from an NSInteger to a CGFloat, no code changes will be needed for the new way.

4

4 Answers

11
votes

The new way is really a new syntax around the old

[myNumber isEqualToNumber:[NSNumber numberWithInt:5]]

which requires an extra call of numberWithInt:; essentially, we're comparing a solution with a single dispatch and zero allocations to a solution with two dispatches, and possibly an allocation/deallocation.

If you do this comparison outside a tight loop, it wouldn't matter. But if you do it in a really tight loop, perhaps while drawing something, you may see a slowndown. That's why I'd stay with the old method of

[myNumber integerValue] == 5
3
votes

The "old way" is one method call plus the comparison operator against two basic types.

The "new way" is one method call plus an extra object creation.

So the old way is more efficient. But unless this is done in a high performance loop (or something similar), the difference is negligible.

As you stated, the new way may be more flexible with regard to the specific type of number.

Personally, I'd choose the form that you find more readable and maintainable unless you have a clear and specific performance issue to deal with.

Though you may have a specific reason to compare a float value or an integer value regardless the original value. In this case, the old way is better because the type of comparison is clear.

3
votes

Short answer: [myNumber integerValue] == 5 is still best.

Long (but you probably shouldn't care) answer: Starting iOS 5, "some" NSNumbers are implemented using tagged pointers (quick google) . This means as long as the NSNumber value fits in 24 bits (for iPhone/iPad's 32-bit ARM processors), no actual instance will be created. So in theory, if you are sure that the values will never overflow 24 bits, you can actually do just myNumber == @5.

Which is not really a good advice. Stick to [myNumber integerValue] == 5. Tagged pointers are there to help the runtime, not the programmers.

0
votes
NSNumber *yourNumber = @(5)

Use when yourNumber should never be nil. it will crash when yourNumber becomes nil

[myNumber isEqualToNumber:yourNumber] 

Use when yourNumber can be nil

myNumber.integerValue == yourNumber.integerValue

note that you have to be aware of the max value yourNumber can take.

If yourNumber will exceed INT_MAX 2147483647, use longValue or longlongValue