来自调试器的消息:由于 Xcode 10.1...图像数组中的内存问题而终止?

Message from debugger: Terminated due to memory issue in Xcode 10.1...image array?

我是新开发者,我的应用有一个 collection 视图(水平滚动),其中包含 32 张图片。我已经为图像、标签和文本创建了数组。 当我到达列表末尾时,应用程序崩溃了。不管我的图片有多大,我得到 'Message from debugger: Terminated due to memory issue'。我使用了 Instruments 工具,这似乎表明图像没有被释放。

我尝试调整图片大小但没有成功。我也试过使用autoreleasepool,可能是我用错了。

我的图像数组是这样设置的,图像 1-32。

let imageArray = [UIImage (named: "1"), UIImage (named: "2"), etc.]

这是我的 collection视图:

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return self.imageArray.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MainCollectionViewCell", for: indexPath) as! MainCollectionViewCell

    cell.imgImage.image = imageArray [indexPath.row]
    cell.lblImageName.text = nameArray [indexPath.row]

    return cell
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    let mainStoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let desVC = mainStoryboard.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController


    desVC.image = imageArray[indexPath.row]!
    desVC.name = nameArray[indexPath.row]
    desVC.text = textArray[indexPath.row]

    self.navigationController?.pushViewController(desVC, animated: true)
}

将图像名称保存在一个数组中,并在数据源中从数组中获取图像名称并构建图像。

let imageArray = ["1", "2"]

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MainCollectionViewCell", for: indexPath) as! MainCollectionViewCell

    cell.imgImage.image = UIImage (named: imageArray [indexPath.row])
    cell.lblImageName.text = nameArray [indexPath.row]

    return cell
}

Note: If you still face memory issue then you might be loading heavy resolution images, better resize them in background thread and assign to imageView on main Thread.

几点观察:

  1. 不要预先加载图像。根据需要加载它们。

    所以,而不是 imageArrayUIImage 的数组,保存图像名称的数组,例如

    let imageNames = ["1", "2", ...]
    

    然后,在 cellForItemAt 中,您可以在此处为该特定单元格实例化 UIImage,例如

    cell.imgImage.image = UIImage(named: imageNames[indexPath.row])
    
  2. 请记住,图像会占用大量内存。无论JPG或PNG的大小如何,当它们在UI中使用时,它们通常每个像素使用4个字节。所以考虑一张 2000×2000 像素的图像,它的 JPG 可能只有 100kb:即使在一个很小的 ​​100×100 图像视图中使用,整个图像也是未压缩的,在这种情况下,会用掉 16mb!因此,请确保您的图像具有适合您 UI 的尺寸。例如。如果你的图像视图是 100×100,那么你可能有三种图像再现,一种是 100×100,用于非视网膜设备,一种是 200×200,用于@2x 视网膜设备,一种是 300× @3x 设备 300。

  3. 关于内存没有释放,三点:

    • 消除您对 UIImage 数组的使用,这将避免强制应用程序将所有图像保存在内存中,即使在任何给定时刻可能并不需要所有图像(见上文第 1 点)。

    • 确保你没有强引用循环。所以关闭有问题的视图控制器,然后使用“调试内存图”并确保视图控制器确实被关闭了。

    • 当您使用UIImage(named:)时,图像将被缓存并且内存不会被释放,直到出现内存压力(例如内存警告)。通常 UIImage(named:) 缓存行为会起作用(当您修复上述问题时),但如果不起作用,请改用 UIImage(contentsOfFile:)。正如 UIImage(named:) 文档警告我们的那样:

      This method looks in the system caches for an image object with the specified name and returns the variant of that image that is best suited for the main screen. If a matching image object is not already in the cache, this method locates and loads the image data from disk or from an available asset catalog, and then returns the resulting object.

      The system may purge cached image data at any time to free up memory. Purging occurs only for images that are in the cache but are not currently being used ...

      If you have an image file that will only be displayed once and wish to ensure that it does not get added to the system’s cache, you should instead create your image using imageWithContentsOfFile:. This will keep your single-use image out of the system image cache, potentially improving the memory use characteristics of your app.