32

I've got some code that relies on comparing two NSIndexPaths and executing different code based on their equality or lack thereof (using -isEqual). Most of the time it works properly, but sometimes it doesn't. I've used the debugger console to test the two indexpaths during code execution, and they look identical to me.

Here's the code:

- (BOOL)selectedStreetIsSameAsLastSelectedStreet
{
    return [self.indexPathOfSelectedStreet isEqual:self.previousObject.indexPathOfSelectedStreet];
}

Here's the output during the execution of the code:

(gdb) po self.indexPathOfSelectedStreet
<NSIndexPath 0x60a0770> 2 indexes [26, 1]
(gdb) po self.previousObject.indexPathOfSelectedStreet
<NSIndexPath 0x55b4f70> 2 indexes [26, 1]
(gdb) p (BOOL)[self.indexPathOfSelectedStreet isEqual:self.previousObject.indexPathOfSelectedStreet]
$2 = 0 '\000'

Am I doing something wrong, or is there another way I can reliably test the equality of two NSIndexPaths?

Stuart
  • 36,683
  • 19
  • 101
  • 139
JoBu1324
  • 7,751
  • 6
  • 44
  • 61

1 Answers1

63

As of iOS 5 you can just use isEqual: (see comments)


Try [indexPath1 compare: indexPath2] == NSOrderedSame.

Maybe you found a bug in NSIndexPath. If you try to create a new NSIndexPath with a path that already exists you should get that one instead. So isEqual: probably just compares the pointers and not the actual indices stored.

Dan Rosenstark
  • 68,471
  • 58
  • 283
  • 421
Sven
  • 22,475
  • 4
  • 52
  • 71
  • 2
    I'm inclined to think this may be a bug as well. I am having the very same issue in iOS 4.2 b3. – Aidan Steele Oct 21 '10 at 05:48
  • I believe this is because `-isEqual:` is just doing a pointer comparison of the two index paths. – Brandon Williams Dec 14 '10 at 19:00
  • Sounds like a bug to me too. From the docs: "NSIndexPath objects are uniqued and shared. If an index path containing the specified index or indexes already exists, that object is returned instead of a new instance.". It appears this is not happening in your code. – Stuart Nov 08 '11 at 16:40
  • 41
    As of iOS 5, `NSIndexPath` now implements an `-isEqual:` method to do what you're expecting. For backwards compatibility, the `-compare:` alternative is the best option. – Dave DeLong Nov 08 '11 at 17:27
  • Dave, does that mean there are occasions where `NSIndexPath`s aren't truly unique? I've seen bugs myself on Mac OS X which suggest that two matching index paths somehow exist at once – Mike Abdullah Feb 09 '12 at 19:41
  • Had the same issue in an app targeting iOS6 and above, this solved the issue and compared the indices instead, as expected. – f.perdition Apr 26 '13 at 09:35
  • @DaveDeLong I believe you are wrong, I couldn't find any documentation regarding this implementation of `-isEqual:` specific to `NSIndexPath` that would do a better job than just a pointer comparison. Or maybe it was there in iOS 5 and then removed again in iOS 6. All in all, lacks of official information and recent issues make the `compare:` solution the best option in all situations. – Cœur Aug 01 '13 at 17:30
  • 5
    @Cœur Prior to iOS 5, `NSIndexPath` instances were uniqued; so requesting an index path of `[1, 1]` twice would give you the *same instance* both times. That changed in iOS 5, and thus a stronger equality check was necessary than simple pointer comparison (one that would actually check that the indices were the same, even if the instances were different). Since developers don't really need to worry about pre-iOS 5 devices too much these days, using `isEqual:` is the correct way to determine if two `NSIndexPaths` are equal. You only need the `-compare:` option if you have to support iOS <5. – Dave DeLong Aug 01 '13 at 20:30