【问题标题】:Message from debugger: Terminated due to memory issue in Xcode 10.1...image array?来自调试器的消息:由于 Xcode 10.1 中的内存问题而终止...图像数组?
【发布时间】:2019-03-26 03:16:50
【问题描述】:

我是一名新开发人员,我的应用有一个包含 32 张图片的集合视图(水平滚动)。我为图像、标签和文本创建了数组。 当我到达列表末尾时,应用程序崩溃了。无论我的图像大小如何,我都会收到“来自调试器的消息:由于内存问题而终止”。我使用了 Instruments 工具,这似乎表明图像没有发布。

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

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

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

这是我的收藏视图:

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

【问题讨论】:

    标签: arrays swift memory xcode10.1


    【解决方案1】:

    一些观察:

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

      因此,而不是 imageArray 的数组 UIImage,保存图像名称数组,例如

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

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

      cell.imgImage.image = UIImage(named: imageNames[indexPath.row])
      
    2. 请记住,图像会占用大量内存。无论 JPG 或 PNG 的大小如何,在 UI 中使用时,它们通常使用每个像素 4 个字节。因此,考虑一个 2000×2000px 的图像,其 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:) 文档警告我们的那样:

        此方法在系统缓存中查找具有指定名称的图像对象,并返回最适合主屏幕的该图像的变体。如果匹配的图像对象尚未在缓存中,则此方法从磁盘或可用资产目录中定位并加载图像数据,然后返回结果对象。

        系统可能随时清除缓存的图像数据以释放内存。仅对缓存中但当前未使用的图像进行清除...

        如果您有一个只显示一次的图像文件并希望确保它不会被添加到系统的缓存中,则应改为使用imageWithContentsOfFile: 创建图像。这将使您的一次性图像远离系统图像缓存,从而可能改善您应用的内存使用特性。

    【讨论】:

    • 谢谢!这行得通。感谢您的时间和知识!
    【解决方案2】:

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

    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
    }
    

    注意:如果您仍然面临内存问题,那么您可能加载过重 分辨率图像,更好地在后台线程中调整它们的大小并分配 到主线程上的 imageView。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-20
      • 1970-01-01
      • 1970-01-01
      • 2018-07-21
      • 2018-09-28
      • 2021-01-04
      • 1970-01-01
      • 2018-03-12
      相关资源
      最近更新 更多