0

I'm showing thumbnails of pictures (from the internet) in a UICollectionView in my app. When there are too many (like 20+) and too high res'd images the app simply crashes. I'm sort of an amateur when it comes to memory management. My question is if I should solve this problem via memory management or scaling the images somehow (if I do that I'm suspecting the images won't be in UIViewContentModeScaleAspectFill)?

Right now I'm using SDWebImage to load my images.

- (UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"thumbCell" forIndexPath:indexPath];
    NSString *URL = [self.album.imageURLs objectAtIndex:(indexPath.item+1)];

    UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake(80, 80, 277, 58)];
    iv.backgroundColor = [UIColor clearColor];
    iv.opaque = NO;
    iv.contentMode = UIViewContentModeScaleAspectFill;
    [iv setImageWithURL:[NSURL URLWithString:URL]];
    cell.backgroundView = iv;

    return cell;
}
meth
  • 1,887
  • 2
  • 18
  • 33
Mathias
  • 233
  • 3
  • 17

1 Answers1

4

The main problem is that while you are dequeueing cells, you are allocating and initialising a new image view for every item in the collection view.

Instead, you should create your own image cell class:

@interface CollectionViewImageCell : UICollectionViewCell
@property (nonatomic) UIImageView *imageView;
@end

@implementation CollectionViewImageCell

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setupImageView];
    }
    return self;
}

#pragma mark - Create Subviews

- (void)setupImageView {
    self.imageView = [[UIImageView alloc] initWithFrame:self.bounds];
    self.imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    // Configure the image view here
    [self addSubview:self.imageView];
}

@end

Then, after registering this class, your cellForItemAtIndexPath: method looks something like this:

- (UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{

    CollectionViewImageCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"thumbCell" forIndexPath:indexPath];

    NSString *URL = [self.album.imageURLs objectAtIndex:(indexPath.item+1)];
    [cell.imageView setImageWithURL:[NSURL URLWithString:URL]];
    return cell;
}

I'm not really that familiar with SDWebImage, I tend to use AFNetworking for this, but I would also make sure that you have an image cache set up.

If you are still having issues with either memory related crashes, or even scrolling performance, then you will probably need to have a better image loading strategy, and perhaps rescale/resample the images on the server side.

Daniel Thorpe
  • 3,911
  • 2
  • 28
  • 28
  • I'm sorry, but I don't understand why the solution is a solution. It too allocates and initializes a new image view for every item in the collection view, doesn't it? It just does it somewhere else. Clearly that makes a difference, but why? – kuipersn May 04 '17 at 16:29
  • @kuipersn - well, no, it only allocates an image view when the cell is initialised. And the system will only initialise as many cell instances as needed. – Daniel Thorpe Jul 27 '17 at 18:18