我一直在搜索这些线程和其他网站,但没有遇到有效和内存友好的方法。所以,这是我的故事:
我的IOS(iPad)应用程序使用精灵表(一个大图像,例如2k x 2k,16 bpp,由许多较小的精灵组成)。我创建了一个sprite atlas类来管理这些工作表,处理精灵动画和其他功能。
想法(在加载方法中)是从文件系统加载工作表,使用CGImageCreateWithImageInRect将其拆分为UIImages(每个sprite一个),然后处理加载的工作表。看起来很简单。
请注意,工作表由initWithContentsOfFile或imageNamed加载到UIImage中(更多内容见下文)。
希望通过使用精灵表来保存文件内存,然后通过仅将实际精灵本身保留为UIImages来保存运行时内存。到目前为止,在我的实验中,这就是我发现的事情:
如果我使用initWithContentsOfFile,我看到(来自Instruments)它似乎打开了一个文件open,fstat64,并关闭了其中的EACH sprite文件。这需要花费大量时间来加载所有精灵。它实际上似乎加载整个工作表,抓住一个精灵,关闭工作表,然后再次加载整个工作表为下一个精灵,直到它们全部创建。此外,它似乎消耗了大量内存(仅在加载第二张纸后以及通过仪器分配后的“接收内存警告”证明)。
接下来我尝试了imageNamed(缓存工作表)。文件加载发生一次,因此速度更快。一切看起来都很好,事实上我可以去,直到很多床单被加载。但最终出现了可怕的“收到内存警告”......几秒钟后,应用程序崩溃了。看起来缓存的图像(即使在拉出精灵后指针设置为null)也永远不会消失。我已经阅读了几篇帖子,这些帖子也说明了这似乎是它的行为(虽然其他帖子说其他的东西,所以这不是决定性的 - 有没有人明确知道?)。
所以似乎两种方法都不需要。我想要的是加载文件,将每个精灵拉出到自己的UIImage中,然后完全释放大表文件的UIImage。
我已经阅读过一个讨论使用initWithContentsOfFile方法设置自己的缓存系统的网站(而不是信任带有imageNamed的IOS计划),这样他们就可以在需要时发布图像。但是,我不认为他们有精灵表。
所以,我把它转交给那里的专家,看看是否有关于如何同时获得快速加载时间和使用最少内存的一些想法。
[是的,我知道IOS 7有SpriteKit。但这也需要在IOS 6.x上运行。]
一个有趣的数据点是,在原始iPad上,imageNamed版本实际上工作正常,没有“收到内存警告”。可能是IOS 5.x.但该应用程序将在iPad 2设备上崩溃。
我不在这里包含代码,因为我所了解的是对与图像处理相关的函数如何使用内存所涉及的机制的理解。
当我在这里时,有人可以澄清这一点:
正确还是错误:当使用CGImageCreateWithImageInRect时,它所做的实际上是从新内存创建一个指定矩形大小的位图,然后从原始UIImage复制像素到这个新内存(而不是设置位图格式)并且指针指向原始UIImage的像素数据)。我认为这是正确的,但需要验证。
谢谢!