【问题标题】:How to Flush Cache to Free up Memory when using UIImage - Swift 3.0使用 UIImage 时如何刷新缓存以释放内存 - Swift 3.0
【发布时间】:2017-12-14 00:01:50
【问题描述】:

在阅读了一些关于 SO 和其他文章的答案(见下文)后,当您将多个图像加载到动画数组中时,管理内存的最佳方法是什么?

http://www.alexcurylo.com/2009/01/13/imagenamed-is-evil/

这是我的目标:

  1. 创建动画数组(见下面的代码)
  2. 动画播放后刷新缓存并加载另一个动画(冲洗、清洗、重复,你懂的:)

正如苹果所说 https://forums.developer.apple.com/thread/17888

使用UIImage(named: imageName) 缓存图像,但在我的情况下,在连续播放 2-3 个动画后,iOS 会终止应用程序(操作系统不会响应内存不足警告而是终止应用程序 - 见代码结尾下面)

我不想缓存图像,我们也可以:

  1. 每次动画完成时刷新内存,然后加载新动画;或
  2. 当用户移动到新场景时刷新内存

这是我的代码:

// create the Animation Array for each animation

func createImageArray(total: Int, imagePrefix: String) -> [UIImage]{
    var imageArray: [UIImage] = []
    for imageCount in 0..<total {
        let imageName = "\(imagePrefix)-\(imageCount).png"
        let image = UIImage(named: imageName)! // here is where we need to address memory and not cache the images

        //let image = UIImage(contentsOfFile: imageName)! // maybe this?

        imageArray.append(image)
    }
    return imageArray
}


// here we set the animate function values

func animate(imageView: UIImageView, images: [UIImage]){
    imageView.animationImages = images
    imageView.animationDuration = 1.5
    imageView.animationRepeatCount = 1
    imageView.startAnimating()
}

// Here we call the animate function

animation1 = createImageArray(total: 28, imagePrefix: "ImageSet1")
animation2 = createImageArray(total: 53, imagePrefix: "ImageSet2")
animation3 = createImageArray(total: 25, imagePrefix: "ImageSet3")

func showAnimation() {
    UIView.animate(withDuration: 1, animations: {
        animate(imageView: self.animationView, images: self.animation1)

        }, completion: { (true) in

        //self.animationView.image = nil // Maybe we try the following?
        //self.animationView.removeFromSuperview()
        //self.animationView = nil

        })
    }

根据 SO 响应,看起来这可能是防止图像被缓存的最佳方法,但它似乎在我的代码中不起作用:

let image = UIImage(contentsOfFile: imageName)!

我也试过了,但似乎也不起作用:

func applicationDidReceiveMemoryWarning(application: UIApplication) {
    NSURLCache.sharedURLCache().removeAllCachedResponses()
}

我还在完成块中尝试了以下文章 (removeFromSuperview),但我也无法让它工作(请参阅上面的代码):

https://www.hackingwithswift.com/example-code/uikit/how-to-animate-views-using-animatewithduration

新代码:

// create the Animation Array for each animation

func createImageArray(total: Int, imagePrefix: String) -> [UIImage]{
    var imageArray: [UIImage] = []
    for imageCount in 0..<total {
        let imageName = "\(imagePrefix)-\(imageCount).png"
        //let image = UIImage(named: imageName)! // replaced with your code below

    if let imagePath = Bundle.mainBundle.path(forResource: "ImageSet1" ofType: "png"),
    let image = UIImage(contentsOfFile: imagePath) {
         //Your image has been loaded   }

        imageArray.append(image)
    }
    return imageArray }

【问题讨论】:

  • 你说:“但它似乎在我的代码中不起作用”。你是什​​么意思?你还在被终止吗?你看不到动画吗?
  • 嗨@AndreaMugnaini - 我已经尝试了各种文章中的建议答案(请参阅标有 ​​// 的 cmets)但是是的,我仍然被终止。动画效果很好,但是当我添加每个额外的动画时,整体内存使用量会增加。我以为我可以简单地使用 self.animationView.removeFromSuperview() 刷新动画,但这似乎也不起作用(内存保持不变)。希望这有助于澄清
  • 您可以检查一下您的 png 文件大小吗?
  • 嗨@AndreaMugnaini - png 文件的平均大小为 100kbs

标签: ios swift uiimage


【解决方案1】:

这很简单。 UIImage(named:) 缓存图片,UIImage(contentsOfFile:) 不缓存。

如果您不想缓存图像,请改用UIImage(contentsOfFile:)。如果你不能让它工作,那么发布你的代码,我们会帮你调试它。

请注意,UIImage(contentsOfFile:) 不会在您的应用程序包中查找文件。它需要图像文件的完整路径。您将需要使用Bundle 方法找到文件的路径,然后将该路径传递给UIImage(contentsOfFile:)

if let imagePath = Bundle.mainBundle.path(forResource: "ImageSet1" ofType: "png"),
  let image = UIImage(contentsOfFile: imagePath) {
     //Your image has been loaded 
}

您的代码正在将所有 3 个动画的所有图像加载到图像数组中并且从不释放它们,因此系统缓存这些图像的事实似乎无关紧要。在内存不足的情况下,系统应该刷新图像的缓存副本,但您的代码仍会将所有这些图像保存在数组中,因此内存不会被释放。在我看来,是您的代码导致了内存问题,而不是系统的图像缓存。

您的代码可能如下所示:

func createImageArray(total: Int, imagePrefix: String) -> [UIImage]{
    var imageArray: [UIImage] = []
    for imageCount in 0..<total {
        let imageName = "\(imagePrefix)-\(imageCount)"
        if let imagePath = Bundle.main.path(forResource: imageName,
            ofType: "png"),
          let image = UIImage(contentsOfFile: imagePath) {
              imageArray.append(image)
        }
    }
    return imageArray 
}

【讨论】:

  • 不。我将把它留给你解决。我没有在 SO 答案中提供可复制粘贴的代码。如果您将我的答案改编为您的代码,您将了解更多信息。
  • 如果要释放内存,则需要释放图像数组。数组持有对图像的强引用,这就是为什么你的内存占用不会减少。
  • 编辑您的问题以在末尾显示新的UIImage(contentsOfFile:) 更改。您描述的错误听起来像是您编写的代码是为了返回一个闭包,而不是一个值。
  • 嗨@Duncan C - 我必须创建一个新组并将图像移出 xassets 文件夹。一切都很好 - 感谢您的帮助
猜你喜欢
  • 2020-12-03
  • 1970-01-01
  • 2023-03-13
  • 2014-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-21
  • 1970-01-01
相关资源
最近更新 更多