In my app, I accidentally used "==" when comparing two NSNumber
objects like so:
NSNumber *number1;
NSNumber *number2;
Later on, after these objects' int
values were set, I accidentally did this:
if (number1 == number2) {
NSLog(@"THEY'RE EQUAL");
}
And, confusingly, it worked! I could have sworn I was taught to do it this way:
if (number1.intValue == number2.intValue) {
NSLog(@"THEY'RE EQUAL");
}
How did using "==" between the two NSNumber
objects work, and why? Does that mean it's okay to compare them that way, or was it just a fluke and this is generally not guaranteed to work every time? It really confused me :(
It's not a fluke. It's due to the tagged pointers feature of the Objective-C runtime while using an ARM64 CPU.
In Mac OS X 10.7, Apple introduced tagged pointers. Tagged pointers allow certain classes with small amounts of per-instance data to be stored entirely within the pointer. This can eliminate the need for memory allocations for many uses of classes like NSNumber, and can make for a good performance boost.[…] on ARM64, the Objective-C runtime includes tagged pointers, with all of the same benefits they've brought to the Mac
Source
That is possibly a fluke.
From NSHipster :
Two objects may be equal or equivalent to one another, if they share a common set of observable properties. Yet, those two objects may still be thought to be distinct, each with their own identity. In programming, an object’s identity is tied to its memory address.
Its possible that your statement evaluated to YES
because number1
and number2
were pointing to the same object. This would not work if they had the same value but were two different objects.
The obvious reason NSNumber
variables would point to the same would be that you explicitly assigned one to the other, like so:
number1 = number2;
But there's one other thing. From this answer :
This is likely either a compiler optimisation or an implementation detail: as NSNumber is immutable there's no need for them be separate instances. probably an implementation optimisation thinking about it. Likely numberWithInt returns a singleton when called subsequently with the same integer.
But anyways, its safest to use isEqualToNumber:
, as there is no telling what other "things" are lurking in the depths of code that may or may not cause it to evaluate YES
From RyPress :
While it’s possible to directly compare NSNumber pointers, the isEqualToNumber: method is a much more robust way to check for equality. It guarantees that two values will compare equal, even if they are stored in different objects.
There two concepts of equality at work here:
In this case, you want value equality. In your code you declare two pointers to NSNumber
objects:
NSNumber *number1;
NSNumber *number2;
But at no point show assignment of a value to them. This means the contents of the pointers can be anything, and quite by chance you have two pointers pointing to the memory locations (not necessarily the same ones) where (number1.intValue == number2.intValue)
happens to be true.
You can expect the behaviour to change in unstable ways - for instance as soon as you add any more code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With