Wrong order in UICollectionView's visibleCells and indexPathsForVisibleItems

Originator:jake
Number:rdar://13417031 Date Originated:14-Mar-2013 01:06 PM
Status:Open Resolved:
Product:iPad SDK Product Version:6
Classification:Other Bug Reproducible:Always
 
Summary:

UICollectionView's visibleCells and indexPathsForVisibleItems return arrays of items that are in the wrong order.

I have a UICollectionView using the default layout that is configured in my Storyboard to display a single row of items scrolling horizontally. I have implemented the UICollectionView's scrollViewDidScroll delegate method. In my implementation of this method I want to determine the 'first visible item' in order to display some information about this item in another part of my app.

To determine the 'first visible item' I ask the collection view for it's visibleCells or the indexPathsForVisibleItems. Given these methods return an ordered array and that the documentation doesn't state otherwise, I'd expect the order of the items in these arrays to match the order of the cells in my collection view. However, in both cases the order of the items that are returned do not always match the order of those items within the collection view.


Steps to Reproduce:

1. Create a UICollectionView with some items.
2. In the collection view's delegate implement the scrollViewDidScroll method.
3. Ask the collection view for its visibleCells and indexPathsForVisibleItems.
4. Examine the order of the items that are returned.
5. Scroll the collection view so that cells are reused.
6. Examine the order of the items that are returned by visibleCells and indexPathsForVisibleItems again.

Expected Results:

The collection view's visibleCells and indexPathsForVisibleItems return arrays of items whose order matches the order of the cells within the collection view.

Actual Results:

Before any cells are reused both methods return arrays of items whose order does match the order of the cells in the collection view - eg.

indexPathsForVisibleItems:
<__NSArrayM 0x756ed60>(
<NSIndexPath 0x817e470> 2 indexes [0, 0],
<NSIndexPath 0x817e5f0> 2 indexes [0, 1],
<NSIndexPath 0x817e6a0> 2 indexes [0, 2],
<NSIndexPath 0x817e750> 2 indexes [0, 3]
)

visibleCells:
<__NSArrayM 0x756bad0>(
1 : <LabelCell: 0x81809f0; baseClass = UICollectionViewCell; frame = (0 32; 226 236); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x8180b20>>,
2 : <LabelCell: 0x8186eb0; baseClass = UICollectionViewCell; frame = (236 32; 226 236); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x8186f40>>,
3 : <LabelCell: 0x81886e0; baseClass = UICollectionViewCell; frame = (472 32; 226 236); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x8188680>>,
4 : <LabelCell: 0x81869c0; baseClass = UICollectionViewCell; frame = (708 32; 226 236); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x8186a50>>
)

After the collection view has scrolled enough to reuse a cell, the order of items returned by these methods no longer matches the order in which the items appear in the collectio view. eg.

indexPathsForVisibleItems:
<__NSArrayM 0x756bad0>(
<NSIndexPath 0x71911a0> 2 indexes [0, 6],
<NSIndexPath 0x817e6a0> 2 indexes [0, 2],
<NSIndexPath 0x817e750> 2 indexes [0, 3],
<NSIndexPath 0x817e800> 2 indexes [0, 4],
<NSIndexPath 0x71b56e0> 2 indexes [0, 5]
)

visibleCells:
<__NSArrayM 0x7572450>(
7 : <LabelCell: 0x8186eb0; baseClass = UICollectionViewCell; frame = (1416 32; 226 236); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x8186f40>>,
3 : <LabelCell: 0x81886e0; baseClass = UICollectionViewCell; frame = (472 32; 226 236); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x8188680>>,
4 : <LabelCell: 0x81869c0; baseClass = UICollectionViewCell; frame = (708 32; 226 236); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x8186a50>>,
5 : <LabelCell: 0x71b1910; baseClass = UICollectionViewCell; frame = (944 32; 226 236); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x7180140>>,
6 : <LabelCell: 0x81809f0; baseClass = UICollectionViewCell; frame = (1180 32; 226 236); clipsToBounds = YES; opaque = NO; layer = <CALayer: 0x8180b20>>
)


Regression:

Notes:
I've attached an Xcode project that demonstrates this bug.

If the API is behaving as it was designed to, then I think either the signature of these methods should change so that they return an unordered set rather than an ordered array or the documentation should be updated to make it clear not to rely on the order of items returned by these methods.

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!