3

I know in Objective-C == is very different from isEqual:. But I am curious about why the following code produces consistently different results on 32bit vs 64bit iOS devices.

NSIndexPath* a = [NSIndexPath indexPathForItem:0 inSection:0];
NSIndexPath* b = [NSIndexPath indexPathForItem:0 inSection:0];
NSLog(@"%@", a == b ? @"YES" : @"NO");
NSLog(@"%@", [a isEqual:b] ? @"YES" : @"NO");

On 32 bit device, e.g. iPhone 5, == always fails (expected).

2016-12-07 09:55:18.019 NSIndexPathTestObjc[18667:1958831] NO
2016-12-07 09:55:18.020 NSIndexPathTestObjc[18667:1958831] YES

On 64 bit device, e.g. iPhone 6s, == succeeds (unexpected).

2016-12-07 09:56:05.503 NSIndexPathTestObjc[18780:1960472] YES
2016-12-07 09:56:05.505 NSIndexPathTestObjc[18780:1960472] YES
Jonathan Beebe
  • 5,241
  • 3
  • 36
  • 42
  • When you are doing the `a == b` you are not comparing pointers, not objects. Since you are create two object they should no match. Why on 64 this is true bevels me too. – rckoenes Dec 07 '16 at 16:25
  • 3
    @rckoenes Typo - you have an extra "not" in your comment. – rmaddy Dec 07 '16 at 16:37

1 Answers1

4

I know in Objective-C == is very different from isEqual:

Yes -- you should use the latter to compare two objects. == only tells you whether the pointers you're comparing are the same.

But I am curious about why the following code produces consistently different results on 32bit vs 64bit iOS devices.

This is probably just be an implementation detail of -indexPathForItem:inSection:, where it might cache index paths that it generates on 64-bit systems and returns the cached object the second time you call the method with the same item, but doesn't on 32-bit systems. Don't rely on this behavior: use -isEqual: for object comparison.

Caleb
  • 124,013
  • 19
  • 183
  • 272
  • 3
    Do you know that `indexPathForItem:inSection:` does that caching or is it just a guess? I think it's much more likely that the == working means that `NSIndexPath` is using tagged pointers on 64-bit devices rather than any caching. – dan Dec 07 '16 at 17:15
  • @dan I have no knowledge of how NSIndexPath is implemented, so just a guess. I've added *might* above to make that more clear. Your guess is probably a better one, but the most important thing here is that it doesn't matter -- it's not a behavior that's promised or that should be relied on. I've seen similar problems with strings, where `==` is used injudiciously and comparisons suddenly stop working when a string that's not a constant is used for the first time. – Caleb Dec 07 '16 at 18:04
  • @Caleb according to a few sources I found strings in Objective-C use “string interning” as an optimization so a string value is shared across multiple pointers, so `==` appears to work. I thought maybe the same thing was going on with `NSIndexPath`, but have not been able to find out for sure. – Jonathan Beebe Dec 07 '16 at 18:47
  • 1
    @dan according to [this answer](http://stackoverflow.com/a/20415382/123781) 64 bit iOS uses tagged pointers. – Jonathan Beebe Dec 07 '16 at 18:52
  • @bejonbee Right, comparing string constants with `==` works because you end up comparing an object to itself, but it fails as soon as you create an `NSString` dynamically and try to compare it to a constant with the same content. There are probably more than a few questions about that here. – Caleb Dec 07 '16 at 19:02