LinShiwei LinShiwei - 7 months ago 47
Swift Question

ScrollToItemAtIndexPath doesn't work sometimes

In my collection, a

UICollectionView
instance, there are 25 cells. The first cell is at indexPath (0,0) and the last cell is at indexPath (0,24).

No matter I scroll from first cell to last cell or from last cell to fist cell, the destination cell is always nil, which seems that the
scrollToItemAtIndexPath
function did not scroll the cell to visible.

While when I scroll from second cell to fist cell, it goes well.

What can I do to scroll correctly between the first and the last?
I have tried
layoutIfNeeded
, but nothing different.

Here is part of my code:

collection.scrollToItemAtIndexPath(indexPath, atScrollPosition: .CenteredVertically, animated: false)
print("indexPath")
print(indexPath)
guard let senderCell = collection.cellForItemAtIndexPath(indexPath) as? ImageCollectionViewCell else{
print(collection.cellForItemAtIndexPath(indexPath))
return
}


And in consoler:

indexPath
<NSIndexPath: 0x79e53110> {length = 2, path = 0 - 24}
nil
indexPath
<NSIndexPath: 0x7b8c2690> {length = 2, path = 0 - 0}
nil
indexPath
<NSIndexPath: 0x79fc48e0> {length = 2, path = 0 - 1}
indexPath
<NSIndexPath: 0x79eb3950> {length = 2, path = 0 - 0}

Answer

I have figured out that there is a time interval between calling scrollToItemAtIndexPath and collectionView updating new visible cells.

So I have changed my code as following:

collection.scrollToItemAtIndexPath(indexPath, atScrollPosition: .CenteredVertically, animated: false)
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(0.1 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue()) {[unowned self] in
    guard let senderCell = collection.cellForItemAtIndexPath(indexPath) as? ImageCollectionViewCell else{
        print("senderCell no found")
        return
    }
    //Do something with the senderCell
}

By adding a delayTime to wait for updating visible cells, we can get the cell we scrolled to.