调整UIIMAGE的内存泄漏



我已经阅读了有关该主题的多个线程,但我的问题仍然存在。当我调整带有以下代码的图像大小时:

extension UIImage {
  func thumbnailWithMaxSize(image:UIImage, maxSize: CGFloat) -> UIImage {
    let width = image.size.width
    let height = image.size.height
    var sizeX: CGFloat = 0
    var sizeY: CGFloat = 0
    if width > height {
        sizeX = maxSize
        sizeY = maxSize * height/width
    }
    else {
        sizeY = maxSize
        sizeX = maxSize * width/height
    }
    UIGraphicsBeginImageContext(CGSize(width: sizeX, height: sizeY))
    let rect = CGRect(x: 0.0, y: 0.0, width: sizeX, height: sizeY)
    UIGraphicsBeginImageContext(rect.size)
    draw(in: rect)
    let thumbnail = UIGraphicsGetImageFromCurrentImageContext()!;
    UIGraphicsEndImageContext()
    return thumbnail
}

override func viewDidLoad() {
    super.viewDidLoad()
    let lionImage = UIImage(named: "lion.jpg")!
    var thumb = UIImage()
    autoreleasepool {
        thumb = lionImage.thumbnailWithMaxSize(image: lionImage, maxSize: 2000)
    }
    myImageView.image = thumb
}

...内存未释放。因此,当我浏览多个ViewControllers(例如使用PageViewController)时,我最终会收到内存警告,并且该应用最终会崩溃。我还尝试通过UIImage(contentsOffile:Path)加载图像,而无需成功。有什么建议么?

我注意到您的代码开始了两个上下文,但仅结束一个上下文。

这是我的扩展名,基本上与您的扩展名相同。由于我没有内存问题,因此可能是问题。

extension UIImage {
    public func resizeToRect(_ size : CGSize) -> UIImage {
        UIGraphicsBeginImageContext(size)
        self.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
        let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext();
        return resizedImage!
    }
}

问题是:

uigraphicSgetImageFromCurrentImageContext()返回自我发行的uiimage。Autorelease Pool保留此图像,直到您的代码将控件返回到Runloop为止,您很长时间以来都不会这样做。要解决此问题,请在使用thumb = nil

var thumb = UIImage()
autoreleasepool {
   thumb = lionImage.thumbnailWithMaxSize(image: lionImage, maxSize: 2000)
   let myImage:UIImage = UIImage(UIImagePNGRepresentation(thumb));
   thumb = nil
}
myImageView.image = myImage

我遇到了一个类似的问题,在尝试了各种解决方案之后,我遇到了以下见解:

使用UIIMAGE和CGIMAGE系统方法处理图像时,它会消耗大量内存。例如,尺寸约4000px x 3000px的简单图像可以占用大约45MB的内存。如果您的应用需要处理多个图像或使用共享扩展名,则您的应用程序可能会消耗所有可用的内存和崩溃。共享扩展名仅为120MB的内存分配有限,因此共享较大的图像(高度/宽度高于7000px)很容易导致应用程序崩溃。这个问题甚至影响了iOS上一些最受欢迎的应用程序。

因此,除了避免处理大型图像文件或使用第三方工具外,没有其他简单的解决方案。

一个这样的开源库解决了这个问题,我用来解决此问题的是SDWebimage,请访问https://github.com/sdwebimage/sdwebimage。将此库导入项目后,您可以使用它来处理图像,而不必担心内存泄漏或崩溃。

这是如何在项目中使用SDWebimage进行调整或压缩图像的一个示例:

func resizeImage(atPath imagePath: URL) -> UIImage? {
    guard let image = UIImage(contentsOfFile: imagePath.path) else { return nil }
    
    guard let thumbnailData = SDImageIOCoder.shared.encodedData(with: image, format: .undefined, options: [.encodeMaxPixelSize: CGSize(width: 1920, height: 1920), .encodeCompressionQuality: 0.7]) else { return nil }
    
    return SDImageIOCoder.shared.decodedImage(with: thumbnailData)
}

最新更新