NSNumber primitive value equality vs isEqualToNumber with Obj-C Literals
Asked Answered
G

4

7

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.

Glenn answered 14/2, 2013 at 20:9 Comment(0)
C
11

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
Chon answered 14/2, 2013 at 20:13 Comment(6)
will autoboxing/unboxing ever come to Objective C ?Useless
@AmoghTalpallikar No, but the next closest thing is here: [myNumber isEqualToNumber:@5]Chon
will == check work for NSNumbers if they represent the same number or bool? myNumber == @5 or status == @YESUseless
@AmoghTalpallikar If status was created as [NSNumber numberWithBool:YES], then status == @YES is going to return YES as well.Chon
so basically == to check wont check them as NSNumber pointers ? or obj C runtime makes sure that only one NSNumber will exist for a particular number ?Useless
@AmoghTalpallikar it's NSNumber that "interns" the number objects that it produces, not the Objective-C runtime.Chon
I
3

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.

Isometric answered 14/2, 2013 at 20:13 Comment(0)
G
3

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.

Gombroon answered 15/2, 2013 at 0:49 Comment(0)
G
0
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

Gruel answered 9/4, 2018 at 18:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.