Question

I am having trouble correctly swapping two UIImageViews stored in an IBOutletCollection. Conceptually, I must be doing something wrong.

Let's say I have an NSMutableArray of indexed data, and an NSMutableArray of indexed UIImageViews, where I would like the two indexed arrays to correspond, i.e. the nth-indexed element of the UIImageView array should reflect the nth data element in the image array.

@property (nonatomic, strong) IBOutletCollection(MyImageView) NSMutableArray* myImages;
@property (nonatomic, strong) NSMutableArray* myData;

At the outset, I sort my IBOutletCollection by x-coordinate so that the appearance on the screen is left-to-right, i.e. the element of index 0 should appear all the way to the left, ..., all the way to the right of the screen.

NSComparisonResult imageSort(id label1, id label2, void* context)
{
    if ([label1 frame].origin.x < [label2 frame].origin.x)
        return NSOrderedAscending;
    else if ([label1 frame].origin.x > [label2 frame].origin.x)
        return NSOrderedDescending;
    else { // Determine using y-coordinate
        if ([label1 frame].origin.y < [label2 frame].origin.y)
            return NSOrderedAscending;
        else if ([label1 frame].origin.y > [label2 frame].origin.y)
            return NSOrderedDescending;
        else
            return NSOrderedSame;
    }
}

Now, whenever I want to swap two members of the data array, I make sure to swap their images as well, so that each UIImageView will always reflect the data in that slot. Let's say the two elements I want to swap have indices frontIndex and backIndex:

// Switch state data in arrays
Data* sendToBack = myData[frontIndex];
Data* bringToFront = myData[backIndex];

myData[frontIndex] = bringToFront;
myData[backIndex] = sendToBack;

MyImageView* sendToBackImg = myImages[frontIndex];
MyImageView* bringToFrontImg = myImages[backIndex];

myImages[frontIndex] = bringToFrontImg;
myImages[backIndex] = sendToBackImg;

The problem happens when I try to animate or update the image array. It appears that when I call animate or update on the updated array element at index 0 and 9, the views that actually update aren't the ones located leftmost and 9th from the left: they're updating in their new locations:

[myImages[frontIndex] animateInWayX]; --> this updates the on-screen view at backIndex
[myImages[backIndex] animateInWayY];  --> this updates the on-screen view at frontIndex

I checked the arrays in the debugger, and the swap did happen -- in other words, the frontIndex element inside the myImages array does show the proper data reflecting the model at myData[frontIndex], so the view array is properly swapped, it's just displaying at a new location on the screen (the location of backIndex, as if it didn't move).

How do I fix this?

Was it helpful?

Solution

Yes, as commenter above pointed out, you are swapping pointers only. Best solution is to copy contents being pointed-to.

// Switch state data in arrays
Data* temp = [[DataObject alloc] init];

[self copyDataFrom:bringToFront into:temp];
[self copyDataFrom:sendToBack into:myData[frontIndex]];
[self copyDataFrom:temp into:myData[backIndex]];

MyImageView* frontImg = myImages[frontIndex];
MyImageView* backImg = myImages[backIndex];

[frontImg updateUsingData:myData[frontIndex]];
[backImg updateUsingData:myData[backIndex]];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top