在 UIImage 和 UIImageViews 中在 Swift 中释放内存

Posted

技术标签:

【中文标题】在 UIImage 和 UIImageViews 中在 Swift 中释放内存【英文标题】:Release memory in Swift in UIImage and UIImageViews 【发布时间】:2015-02-25 12:52:34 【问题描述】:

我正在开发一个包含多个视图的应用程序。每个视图包含几个由 UIImageView.animate 形成的动画。我遇到的问题是,每次我打开一个新的 View 内存并没有减少,在 iPhone 4 上增加到 320 Mb,retonrando 内存错误“由于内存错误而终止”。我找不到如何在 Swift 中自动释放内存,因为在 Objective-C 中,如果我能看到它更可取 imageWithContentOfFile 而不是命名:...

我使用它来将图像添加到 UIImage 对象:

var leftCorner: UIImage =  UIImage(named: "navegacio_esquerra")!

要在 UIImageView.animationImages 中添加图像数组,我使用这个:

var thirdSisterHeadList: [Int] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 33, 32, 33, 34, 33, 32, 33, 34, 33, 32, 33, 34, 33, 32, 33, 34, 33, 66, 67, 68]

        var thirdSisterHeadImageList: [UIImage] = []

        for i in thirdSisterHeadList
            var imageName = "pantalla_12_03_caps_c_\(i).png"
            thirdSisterHeadImageList += [UIImage(named: imageName)!]
        
thirdSisterHead.animationImages = thirdSisterHeadImageList

【问题讨论】:

【参考方案1】:

此评论没有意义

我找不到如何在 Swift 中自动释放内存,因为在 Objective-C 中,如果我能看到使用 imageWithContentOfFile 而不是命名:更可取。

Swift 和 ObjC 以相同的方式管理内存。对于这种工作,您肯定会想要使用named:,因为它可以让系统为您执行更好的内存管理。当内存紧张时,它可以自动清除不需要的表示。

从 Instruments 中的 Allocations 工具开始。确保这些图像实际上是您的记忆要去的地方。很可能是这种情况,但是对于内存分析,您需要的是数据,而不是猜测。

您多次使用相同的图片。这可能没问题,但您应该验证 pantalla_12_03_caps_c_33.png 的每个实例实际上是相同的 UIImage (这确实应该自动为您工作,所以我不强烈怀疑这里有问题)。

要为图像设置动画,它会希望它们都在内存中解码。即便如此,在 iPhone 4 上 30 张图片 320MB 听起来还是很多的。每张图片大约 10MB。全屏 iPhone 4 图像应该更像 2MB (640*960*4)。如果您使用的是非常高分辨率的图像,您可能希望为不同的设备提供多种分辨率,这样它就不必处理太多会被丢弃的数据。

内存没有被恢复的事实几乎可以肯定意味着你的视图没有被释放。这表明您有一个保留循环,或者您可能一直调用addSubview: 来添加一个图像视图而不删除旧的图像视图(这是一个很常见的错误)。在您的视图控制器中覆盖 dealloc 并确保它在您期望的时候消失。确保你没有在这个视图控制器之外的某个地方持有thirdSisterHead

不相关的旁注:您的 for-in 循环确实很难做到这一点。这段代码可以简化并将所有变量替换为常量,并且无需为+=创建一个临时的[UIImage]

let thirdSisterHeadList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 33, 32, 33, 34, 33, 32, 33, 34, 33, 32, 33, 34, 33, 32, 33, 34, 33, 66, 67, 68]
let thirdSisterHeadImageList = thirdSisterHeadList.map  
    UIImage(named: "pantalla_12_03_caps_c_\($0).png")! 

self.thirdSisterHead.animationImages = thirdSisterHeadImageList

【讨论】:

感谢您的回答。第一条评论确实是 Obj-C 和 Swift 中的内存管理是相同的,但是在我使用推荐我使用的方法对这个主题进行的所有搜索中,我使用了 named: 而不是方法 imageWithContentOfFile :,这就是我做这个评论的原因.另一方面,我充的图片不超过12Kb,320MB是所有应用的积累。另一方面,我尝试覆盖 dealloc,但 Swift 无法覆盖 dealloc,因为它标记为不可用。 您对named: 更好的理解对于这种情况是正确的。请注意,图像需要的内存与其总的未压缩显示大小成正比,而不仅仅是它们在磁盘上的压缩大小,但 12kb 文件不太可能被炸毁到那个级别。在 Swift 中,dealloc 现在称为deinit。您应该在 Instruments 中使用 Heapshot 来确定每个操作泄漏了多少内存。 好的,但是,deinit如何释放必要的空间?? 您不使用deinit 发布任何内容。您使用deinit 来确定您的视图控制器是否实际上被销毁(通过添加日志语句)。如果不是,则您需要处理一个保留循环。 也许我的问题比这更深,因为我正在开发的是一个儿童故事,它由 14 个场景组成,每个场景有 3 或 4 个动画。每个场景都在为每个场景开发一个故事板,并为每个场景开发一个 VC。为了创建动画,我将一组图像分配给 animationImage 和一个浮点数,在 UIImageView 的 animationDuration 中指示动画的持续时间。当运行 Segue VC 1al VC 2 时,我可以清空 VC 的全部内容 ??我很抱歉并感谢您为我提供的所有帮助。非常感谢

以上是关于在 UIImage 和 UIImageViews 中在 Swift 中释放内存的主要内容,如果未能解决你的问题,请参考以下文章

比较具有 UIImageViews 的 UIButtons

滚动 UITableView 时 UIImageViews 变黑

子类 UIView 不显示添加到它的 UIImageViews

滚动UITableView时,UIImageViews变黑

创建 UIImage 抠图

UIImageView 在 XIB 中使用哪个 UIImage 方法?