0

I faced and issue with images using too much memory when running the app. A 905kb SVG image was taking around 150mb when presented and this image was being cached by the system. Loading several different SVG images on different pages led to memory pressure issue.

So I started looking into image downsampling and found a solution. I managed create a function to downsample the image based on size of the image (Had help with it).Currently I can downsample the image by using a downsampler class which needs to be set as a custom class for every imageView which I want to enable downsampling.

But I am trying to create an IBDesignable extension for UIImageView so that I can use any custom class but still get the benefit of downsampling the image.

This is the code for downsampling class

import UIKit

class DownsamplingImageView: UIImageView {
    
    @IBInspectable
    var downSample: Bool = true {
        didSet {
            setNeedsLayout()
        }
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        
        if downSample, let image = self.image {
            let targetSize = self.bounds.size
            let downsampledImage = image.downsample(to: targetSize)
            self.image = downsampledImage
        }
    }
}

extension UIImage {
    
    func downsample(to targetSize: CGSize) -> UIImage? {
        let sourceSize = self.size
        let widthRatio = targetSize.width / sourceSize.width
        let heightRatio = targetSize.height / sourceSize.height
        let scaleFactor = max(widthRatio, heightRatio)
        
        let scaledSize = CGSize(width: sourceSize.width * scaleFactor, height: sourceSize.height * scaleFactor)
        
        UIGraphicsBeginImageContextWithOptions(scaledSize, false, 0.0)
        self.draw(in: CGRect(origin: CGPoint.zero, size: scaledSize))
        let downsampledImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return downsampledImage
    }
}

This is how I tried to make an extension but unfortunately it doesn't work.

import UIKit
@IBDesignable
extension UIImageView {
    
    @IBInspectable
    var downSample: Bool {
        get {
            return image != nil
        }
        set {
            setNeedsLayout()
        }
    }
    
    override open func layoutSubviews() {
        super.layoutSubviews()
        
        if downSample, let image = self.image {
            let targetSize = self.bounds.size
            let downsampledImage = image.downsample(to: targetSize)
            self.image = downsampledImage
        }
    }
}

extension UIImage {
    
    func downsample(to targetSize: CGSize) -> UIImage? {
        let sourceSize = self.size
        let widthRatio = targetSize.width / sourceSize.width
        let heightRatio = targetSize.height / sourceSize.height
        let scaleFactor = max(widthRatio, heightRatio)
        
        let scaledSize = CGSize(width: sourceSize.width * scaleFactor, height: sourceSize.height * scaleFactor)
        
        UIGraphicsBeginImageContextWithOptions(scaledSize, false, 0.0)
        self.draw(in: CGRect(origin: CGPoint.zero, size: scaledSize))
        let downsampledImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        
        return downsampledImage
    }
}

Could someone please help or explain why the extension on UIImageView doesn't work but using custom class works? Also is there anyway to make the extension work?

PS: 150mb usage reduced to just 6mb usage and fortunately its being released right when user leaves the page ! Just incase anybody want to enable downsampling, the first code works perfectly, all you have to do is set the UIImageView custom class as DownsamplingImageView

Zyfe3r
  • 653
  • 6
  • 24
  • *"A 905kb SVG image..."* -- SVG files are vector definitions. If that is using *"150mb when presented"* then ***you*** are initializing it to a very large size. What code are you using to render the SVG file as a `UIImage`? – DonMag Jun 05 '23 at 15:27

0 Answers0