在 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 中释放内存的主要内容,如果未能解决你的问题,请参考以下文章
滚动 UITableView 时 UIImageViews 变黑