Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSNumber primitive value equality vs isEqualToNumber with Obj-C Literals

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.

like image 411
Alex Pretzlav Avatar asked Feb 14 '13 20:02

Alex Pretzlav


3 Answers

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
like image 177
Sergey Kalinichenko Avatar answered Nov 01 '22 20:11

Sergey Kalinichenko


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.

like image 24
rmaddy Avatar answered Nov 01 '22 18:11

rmaddy


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.

like image 3
John Estropia Avatar answered Nov 01 '22 19:11

John Estropia