使用UIImage时如何刷新缓存以释放内存 - Swift 3.0

时间:2017-12-10 01:20:05

标签: ios swift uiimage

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

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

以下是我的目标:

  1. 创建动画数组(参见下面的代码)
  2. 动画播放后刷新缓存并加载另一个动画(冲洗,清洗,重复,你得到它)。
  3. 正如Apple所述 https://forums.developer.apple.com/thread/17888

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

    我不想缓存图片,而是我们可以:

    1. 每次动画完成后刷新内存,然后加载新动画;或
    2. 当用户移动到新场景时刷新内存
    3. 这是我的代码:

      // 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 }
      

1 个答案:

答案 0 :(得分:4)

这很简单。 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 
}