Search code examples
iosuitableviewuiimageviewuiimagescale

iOS - Image that is downloaded in the background and assigned to UITableViewCell imageView does not fill view


Similar things that don't really answer my issue

What I am doing

User taps a 'save' button. This creates a new table view cell. Images are downloaded in another thread.

  • I download an image from a URL
  • Save the image
  • Scale the image while keeping the aspect ratio
  • Set the image to the UITableViewCell imageView that was created earlier

Problem

The problem is the last step. I want the image to fill the view and get clipped. However, the image is always drawn such that it completely fits inside the imageView with some empty white space. The images does not even fill the cell's imageView in a single dimension. It is right aligned with whitespace on the top, bottom, and left.

When I tap on the cell after the mis-drawn image is set, the cell redraws and the image is drawn to fill the imageView in one dimension but is still not clipped.

Code

I create the cell and set a temporary image

cell.imageView.image = [UIImage imageNamed:@"125-food.png"];
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
cell.imageView.layer.masksToBounds=YES;

I start the job like this:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 500000 * NSEC_PER_USEC), dispatch_get_current_queue(), ^{ /*Stuff*/ });

Scale image code

CGFloat newHeight;
CGFloat newWidth;
if(image.size.width>image.size.height)
{
    newHeight = 44.0;
    newWidth = image.size.width * newHeight / image.size.height;
}
else
{
    newWidth = 44.0;
    newHeight = image.size.height * newWidth / image.size.width;
}

CGRect newRect = CGRectMake(0,0,newWidth,newHeight);
UIGraphicsBeginImageContext(newRect.size);
[image drawInRect:newRect];
UIImage * newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;

And then I set the newImage in the cell

cell.imageView.image = newImage;

Screen shots

Screen shots of cells

The new cell does not fill the 44x44 image view, and the old cells do not get clipped.


Solution

  • I appear to have solved my problems. Firstly the way I was scaling images was incorrect. I found a better way here UIImage: Resize, then Crop

    I used the method proposed by Anybody. So, by working out the scale factor, I can create an image of the correct size, with the correct scaling. This saves me from having to clip the image in the view.

    CGFloat scaleFactor = 1.0;

    //Deciding which factor to use to scale the image (factor = targetSize / imageSize)
    if (image.size.width > targetSize.width || image.size.height > targetSize.height)
        if (!((scaleFactor = (targetSize.width / image.size.width)) > (targetSize.height / image.size.height))) //scale to fit width, or
            scaleFactor = targetSize.height / image.size.height; // scale to fit heigth.
    
    UIGraphicsBeginImageContext(targetSize); 
    
    //Creating the rect where the scaled image is drawn in
    CGRect rect = CGRectMake((targetSize.width - image.size.width * scaleFactor) / 2,
                             (targetSize.height -  image.size.height * scaleFactor) / 2,
                             image.size.width * scaleFactor, image.size.height * scaleFactor);
    
    //Draw the image into the rect
    [image drawInRect:rect];
    

    Now I just have to set the image. Set UIImageView Size in UITableViewCell when UIImage loaded from URL? suggests that I should be able to set the image. But that gave me a result like in my screen shot. Apparently, I also do not have control of the table cell views.

    In Resize UIImageView in UITableViewCell there is a suggestion of setting the transform on the imageView. I thought since the thumbnail image is already made to size, I should just scale to 1.0.

    cell.imageView.transform = CGAffineTransformMakeScale(1.0, 1.0);
    

    And this seems to work well so far!

    My temporary icons appear to work, and saved thumbnails are displayed correctly. The difference is that the temp images are not the same size. So I scaled up my icons to the correct size. My images now display correctly!