Search code examples
iosobjective-cuiimageviewuicollectionviewcell

iOS 10.3 beta - ImageView in CollectionViewCell bug?


Is anyone else having problems displaying an image (UIImageView) in a collection view cell in iOS 10.3 beta 6? The cells that are initially visible show the image, but new/dequeued cells that become visible as I scroll do not display the image. This is in Objective C, haven't tried it in Swift yet. Cell definition:

@interface StdCollectionViewCell : UICollectionViewCell

@property (strong, nonatomic) IBOutlet UIImageView *fileImage;      // for thumbnail image of file
@property (strong, nonatomic) IBOutlet UITextView *fileTextView;    // for name or description of file
@property (nonatomic) BOOL unviewed;                                // has the user viewed this file yet

@end

From cellForItemAtIndexPath, I get a UIImage (which I have verified is not null), then set the cell's fileImage.image property:

theCell.fileImage.image = image;                                                                                        // set the thumbnail image

I tried using setNeedsDisplay after assigning the image, but that didn't help.


Solution

  • While attempting to create a simple app that exhibited the problem, I was able to figure out why the images weren't getting displayed.

    Before prefetching was around (probably when iOS 9 was current, perhaps even before that), I had created code to dispatch creating/retrieving the images to another queue. Once they were ready, the code to assign them to the cell's UIImageView object was dispatched back to the main queue.

    In order to not waste cycles if the user scrolled the cell back off the screen before the image was ready, I checked several times to see if the cell was visible using indexPathsForVisibleItems before proceeding with the next step. If the path wasn't in that array, I would just return nil for the image. Also, when I was ready to assign the image to the UIImageView.image property, I used the collection view's cellForItemAtIndexPath.

    Obviously, with prefetching, this shouldn't work, because indexPathsForVisibleItems shouldn't contain prefetched cells that aren't visible yet, and cellForItemAtIndexPath is supposed to return null if the cell isn't visible (so the message to set the image would be sent to null).

    During my initial debugging I was getting an image; however I didn't notice that the cell variable I was trying to assign that image to was null!

    Strangely, this code has been working in iOS 10 up until now, which would seem to indicate the prefetched cells were being included in the visible items array and cellForItemAtIndexPath was working for prefetched but not visible cells. It seems that has been fixed now, which caused my code to break.

    EDIT: Not so strange after all. I just realized that the previous release of the app was completed using Xcode 7, which means it was built using the iOS 9 SDK, which didn't have prefetching. So even though it was running on iOS 10, it didn't use the prefetching. When I opened the app in Xcode 8, it enabled Prefetching on the collection view by default. This isn't the first time I tested the app in Xcode 8, but I must not have tried scrolling that collection view before while working with Xcode 8. END EDIT.

    The quick fix is to turn off the collection view's prefetching, which is what I did because this is an Enterprise app for our own internal use, not something that has to go in the App Store, so it doesn't matter if it is a little slower.

    I should have followed @matt's advice (which I have even given to others in the past :) ) and tried to produce a simple complete example first, and I probably would have figured this out before posting my question. But I had some other things coming up that day and was feeling impatient, so I posted anyway. I'll try to learn from my mistake :).