Search code examples
iosxcodeuiimageviewuiimageretina

Xcode @2x image suffix not showing as Retina in iOS


I am having difficulties with retina images.

The screenshot below shows the UICollectionView with a UIImageView contained within each UICollectionViewCell.

Within the app I have a large image 512x512 pixels called travel.png. The green circle shows what is displayed on the app when I name this file: travel.png. The blue circle shows what I see when I update the image name to be [email protected] (i.e. retina naming).

I was hoping due to the large size of the image (512x512) that simply adding the @2x suffix would be enough to convert it to twice the definition (i.e. retina) but as you can see from the two screenshots, both version images show as non-retina.

How can I update the image so that it will display in retina?

travel.png: travel.png filename used

[email protected]: travel@2x.png filename used * Updated * Following request in comments below:

I load this image by calling the following function:

// Note - when this method is called: contentMode is set to .scaleAspectFit & imageName is "travel"
public func setImageName(imageName: String, contentMode: ContentMode) {

    self.contentMode = contentMode
    if let image = UIImage(named: imageName) {
        self.image = image
    }        
}

Here is how the image appears in Xcode before the app renders it (as you can see it is high enough definition):

enter image description here


Solution

  • TL;DR;

    Change the view layer's minificationFilter to .trilinear

    imageView.layer.minificationFilter = .trilinear
    

    as illustrated by the device screenshot below enter image description here

    As Anton's answer correctly pointed out, the aliasing effet you observe is caused by the large difference in dimensions between the source image and the image view it's displayed in. Adding the @2x suffix won't change anything if you do not change the dimensions of the source image itself.

    That said there is an easy way to improve the situation without resizing the original image: CALayer offers some control over the method used by the graphics back-end to resize images : minificationFilter and magnificationFilter. The first one is relevant in your case since the image size is being reduced. The default value is CALayerContentsFilter.linear, just switch to .trilinear for a much better result (more info on those wikipedia pages). This will require more GPU power (thus battery), especially if you apply it on many images.

    You should really consider resizing the images before displaying them, either statically or at run-time (and maybe cache the resized versions). In addition to the bad visual quality, using such large images in quantities in your UI will decrease performance and waste lots of memory, leading to potentially other issues.