【问题标题】:creating an autorelease pool and draining it in a different context创建一个自动释放池并在不同的上下文中耗尽它
【发布时间】:2012-02-23 15:53:19
【问题描述】:

在视图控制器中,我有一个 UIImageView 作为子视图。在 willRotateToInterfaceOrientation 上,我将其替换为不同的 UIImageView。如果两者同时在内存中,有时会因为图像非常大而导致崩溃。所以我想确保在制作新的之前完全解除第一个。当我对它调用 removeFromSuperview 时,我认为它基本上是稍后自动释放的,但我需要立即释放它。

所以在创建 UIImageView 时我似乎需要我自己的自动释放池,然后在 removeFromSuperview 调用之后调用 willRotateToInterfaceOrientation 时将其排空。但是文档说:

自动释放池应始终在相同的上下文中耗尽(例如 作为方法或函数的调用,或循环体)在 它是创建的。自动释放池“内联”使用。那里 通常应该不是你应该创建自动释放池的理由 对象的实例变量。

那么“正确”的做法是什么?

【问题讨论】:

    标签: objective-c memory-management autorelease


    【解决方案1】:

    最好的办法是优化您的图像。必须在同一上下文中分配和排出自动释放池。您应该首先尝试减小图像的大小。如果它们是 png 的尝试pngcrush。如果图像仍然很大,请考虑使用mmap 一次加载部分图像。

    Performance Tuning

    对资源施加大小限制。
    避免加载较大的资源文件,而应该加载较小的资源文件。而不是使用高分辨率 图像,请使用大小适合基于 iOS 的设备的图像。如果 您必须使用大型资源文件,找到仅加载部分的方法 您在任何给定时间需要的文件。例如,而不是 将整个文件加载到内存中,使用 mmap 和 munmap 函数 将文件的部分映射到内存中和从内存中映射出来。了解更多信息 关于将文件映射到内存,请参阅文件系统性能 指导方针。

    【讨论】:

    • 在作为 UIImage 加载后,通过压缩减少图像的磁盘大小是否会影响 RAM 占用?我假设它总是以未压缩的形式存储在 RAM 中?
    • 它至少有助于减少内存峰值,因为它已从磁盘加载图像以将其放入 RAM。
    • 啊,好的,谢谢。但是与未压缩的图像相比,实际文件大小相形见绌。如果我可以在制作新图像之前释放旧图像,我可以将峰值减少一半,真的没有办法吗?顺便说一句,mmap 看起来很有趣,我不知道..
    • 我想你可以尝试延迟加载下一个图像,直到下一个运行循环,这应该让自动释放池有时间清理。尝试使用(void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay 并为延迟传递 0。
    • 你最后的建议是我最终做了什么,谢谢。它似乎是唯一真正确保在制作新内容之前从内存中删除旧内容的方法。这意味着中间有短暂的黑屏,但我认为这是不可避免的。
    【解决方案2】:

    将自动释放池视为线程本地堆栈。您不会跨上下文或其他自动释放池持续存在 - 弄乱了顺序。将自动释放池作为 ivar 通常是一个错误。从多个线程使用自动释放池也是一个错误。

    在您需要的每个地方创建一个,并在该上下文中在该线程上销毁,而不会弄乱排序,您会没事的。这可能意味着在您提到的每种方法中创建和销毁一个。它们的创建和销毁速度非常快。

    如果您需要在该上下文之外保留对另一个对象(例如您的图像)的引用,以确保它在您需要时一直存在,请这样做。

    【讨论】:

      猜你喜欢
      • 2015-08-11
      • 1970-01-01
      • 2011-06-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多