In the code below, I download image URLs from a text file, store it in a NSMutableArray, then download the images from from those URLS in CellforItemAtIndexPath. However, when I
I noticed a bunch of downvotes without comments and after reading my answer again I guess the original accepted answer (below the line) could have been better.
There are a few things going on with these kinds of problems. The UITableView only creates just enough UITableViewCells to display every cell in view plus what's going to scroll into view. The other cells are going to get re-used after they scroll out of view.
This means when you're scrolling fast the cell gets set up multiple times to fetch an image async and then display it because it's pretty slow fetching the image. After the image loads it will show itself on the cell that originally called to fetch it, but that cell might be re-used already.
Nowadays I have a bufferedImage: UIImage? property on whatever data class I use as data for the UITableViewCells. This will initially always be nil so I fetch the image async and when the dispatch_async returns it will store it there so the next time I need to show this cell it's ready, and if it's still the same cell I will also display it in the cell.
So the right way to do it is:
So there's one object you pass along in your async call so you can store the fetched image. There's another object that's in the current cell that you can compare to. Often the cell already got reused before you got the image, so those objects are different by the time your image is downloaded.
Scrolling and rotating CollectionViews always has been a bit problematic. I always have the same problem, images that appear in the wrong cells. There is some kind of optimization going on for the collectionview that affects images but not labels. To me it's a bug but it still isn't solved after three iOS releases.
You need to implement the following:
https://developer.apple.com/library/ios/documentation/uikit/reference/UICollectionViewLayout_class/Reference/Reference.html#//apple_ref/occ/instm/UICollectionViewLayout/shouldInvalidateLayoutForBoundsChange:
This should always return YES basically to always refresh it. If this solves your problem then you could look into not executing the whole redraw every time as it's bad for performance. I personally spent a lot of time in counting if a screen had passed or line had passed and so on but it became stuttery instead so I ended up just returning YES. YMMV.