Search code examples
objective-cnsset

Unexpected behavior with NSMutableOrderedSet


Using an NSMutableOrderedSet, I'm getting unexpected behavior.

I set an object at index 0. In the next call, I read out the object at index 0. How is it that the pointer I get back is not the same as the one I just inserted?

- (void)setRecentObject:(SomeObject *)recentObject
{
    // self.activeQueue is a viable instance of NSMutableOrderedSet

    [[self activeTileQueue] insertObject:recentObject atIndex:0];
    SomeObject *whatIJustInserted = [[self activeTileQueue] objectAtIndex:0];

    DebugLog(@"set url at zero: %@, and read back url at zero: %@",[recentObject someDescription], [whatIJustInserted someDescription]);

}

To my thinking, at the end of this method, recentObject should == whatIJustInsereted -- and yet both in my logging statement and when I evaluate the pointers after setting a breakpoint, the objects are different instances of SomeObject. Is there something I don't understand about NSMutableOrderedSet?


Solution

  • The reason this did not behave as expected is because the receiver activeTileQueue (the NSMutableOrderedSet instance) already contained the member.

    While I specifically sought the use of a set versus an array because I didn't want duplicates of any objects inserted, my assumption about how the insertion would work in this case was incorrect. I assumed that if the set already contained the member I was attempting to insert, that rather than be re-insereted, the member would be repositioned to the index passed in -insertObjectAtIndex. This was incorrect.

    If the receiver already contains the member, it is not re-inserted or re-ordered. In short, nothing happens. To obtain the originally desired behavior, I would have to either remove the original member and re-insert it, or use another method on NSMutableOrdered set to reposition/exchange the index within the set, eg:

    NSIndexSet *replacementSet = [NSIndexSet indexSetWithIndex:[[self activeTileQueue] indexOfObject:recentObject]];
    [[self activeTileQueue] moveObjectsAtIndexes:replacementSet toIndex:0];