ARC在导航控制器中“返回”时不释放内存 - 而且它正在减慢我的uipageviewcontroller

时间:2022-02-07 14:20:56

Part of the app I'm working on involves a UIPageViewController, where each page displays an 'entry' that is stored in Core Data. An entry includes, among other things, some images that are being compressed and stored as NSData. Thus, to load these images and display them on a page, I'm using imageWithData, i.e.

我正在处理的应用程序的一部分涉及UIPageViewController,其中每个页面显示存储在Core Data中的“条目”。除了其他之外,条目还包括一些被压缩并存储为NSData的图像。因此,要加载这些图像并将它们显示在页面上,我正在使用imageWithData,即

photo.image = [UIImage imageWithData:entry.photo];

The problem is that imageWithData is not particularly quick, and so flipping through pages is not as responsive as I would like. My best attempt at remedying this situation has been to preload a number of the view controllers that are displayed by my UIPageViewController into an array. (Not sure if that's the best thing to do, but there you have it)

问题是imageWithData不是特别快,因此翻页不像我想的那样响应。解决这种情况的最佳尝试是将我的UIPageViewController显示的一些视图控制器预加载到一个数组中。 (不确定这是不是最好的事情,但你有它)

So, to clarify, I have a navigation controller, which contains viewControllerA, which then links to viewControllerB - which displays the UIPageView and the entryControllers (one entryController on each page). The problem is that when I use the navigation bar to go back from viewControllerB to viewControllerA, I want viewControllerB's array of entryControllers to be released from memory. But, ARC doesn't seem to be doing so. Therefore, after going back and forth between viewControllerA and viewControllerB a few times, turning a few pages each time, I start to get memory warnings - which ends up clearing the current array of entryControllers, and defeats the purpose of having that array, since the entries then have to be reloaded every time I get a memory warning.

所以,为了澄清,我有一个导航控制器,它包含viewControllerA,然后链接到viewControllerB - 它显示UIPageView和entryControllers(每页上有一个entryController)。问题是,当我使用导航栏从viewControllerB返回到viewControllerA时,我希望viewControllerB的entryControllers数组从内存中释放。但是,ARC似乎并没有这样做。因此,在viewControllerA和viewControllerB之间往返几次,每次翻几页,我开始得到内存警告 - 这最终清除了当前的entryControllers数组,并且失败了拥有该数组的目的,因为每次收到内存警告时都必须重新加载条目。

In short, ARC isn't clearing any of the memory I've allocated for viewControllerB when I go back to viewControllerA via my navigation controller. I don't like that. If anyone could suggest a reason that this is happening, or let me know if I'm going about this whole thing the wrong way, it would be hugely appreciated. I'm just trying to speed up the transition from one page to the next!

简而言之,当我通过导航控制器返回viewControllerA时,ARC没有清除我为viewControllerB分配的任何内存。我不喜欢那样。如果有人能够提出这种情况发生的原因,或者让我知道如果我以错误的方式处理这一切,那将非常感激。我只是想加快从一个页面到下一个页面的过渡!

Thanks a bunch.

谢谢你们。

2 个解决方案

#1


5  

The only reason for ARC to not release your memory is that you still are retaining it somewhere. Only you know where that is.

ARC不释放记忆的唯一原因是你仍然将它保留在某个地方。只有你知道它在哪里。

Usually, this is caused by a retain cycle, which can happen easily with blocks.

通常,这是由保留周期引起的,这可以通过块轻松实现。

However, it is just as likely that you are keeping a pointer to the object someplace, in a controller, an iVar, or some collection.

但是,您可能会在某个位置,控制器,iVar或某些集合中保留指向对象的指针。

Have you run the static analyzer on your code? It's pretty good at finding some of those things.

您是否在代码上运行静态分析器?找到其中的一些东西非常好。

What does instruments tell you? It's got some neat tools for finding leaks and retain cycles.

乐器告诉你什么?它有一些简洁的工具来查找泄漏和保留周期。

EDIT

You can have as many references to any object that you want. Once the count goes to zero, it will be released.

您可以对所需的任何对象具有尽可能多的引用。一旦计数变为零,它将被释放。

The problem is that you are holding an array of strong pointers to view controllers as a cache. If you want them released, you have to manually nil those pointers. You are somehow pre-loading controllers into an array. They will stay alive until you unload them.

问题是你持有一组强指针来查看控制器作为缓存。如果你想要它们发布,你必须手动nil这些指针。您以某种方式将控制器预加载到阵列中。他们会活着,直到你卸下它们。

So, as long as you have a strong pointer to something, it will stay around.

所以,只要你有一个强大的指针指向某个东西,它就会保持不变。

#2


1  

Jody's edit, specifically mentioning setting pointers to nil, is what got the ball rolling for me in terms of understanding, and in the end I was able to figure out my problem by setting certain pointers to nil when my "viewControllerB" disappeared. Along the way, however, I also realized another important point - large images in core data are a huge memory burden, and in iOS 5, this can be remedied by setting an option to allow for external storage. So for anyone else who's a relative beginner like me and might come across a similar memory problem, this is a key way to limit the amount of memory being eaten by managed objects storing large amounts of data - your images (or whatever large amount of data) are saved to file automatically, without you having to do anything different in code.

Jody的编辑,特别提到设置指向nil的指针,就是在理解方面让我滚动的原因,最后我通过在我的“viewControllerB”消失时设置指向nil的指针来解决我的问题。然而,在此过程中,我还意识到另一个重点 - 核心数据中的大图像是巨大的内存负担,而在iOS 5中,可以通过设置允许外部存储的选项来解决这个问题。因此,对于像我这样的初学者而且可能遇到类似内存问题的其他人来说,这是限制存储大量数据的托管对象所占用的内存量的关键方法 - 您的图像(或任何大量数据) )自动保存到文件,而不必在代码中做任何不同的事情。

#1


5  

The only reason for ARC to not release your memory is that you still are retaining it somewhere. Only you know where that is.

ARC不释放记忆的唯一原因是你仍然将它保留在某个地方。只有你知道它在哪里。

Usually, this is caused by a retain cycle, which can happen easily with blocks.

通常,这是由保留周期引起的,这可以通过块轻松实现。

However, it is just as likely that you are keeping a pointer to the object someplace, in a controller, an iVar, or some collection.

但是,您可能会在某个位置,控制器,iVar或某些集合中保留指向对象的指针。

Have you run the static analyzer on your code? It's pretty good at finding some of those things.

您是否在代码上运行静态分析器?找到其中的一些东西非常好。

What does instruments tell you? It's got some neat tools for finding leaks and retain cycles.

乐器告诉你什么?它有一些简洁的工具来查找泄漏和保留周期。

EDIT

You can have as many references to any object that you want. Once the count goes to zero, it will be released.

您可以对所需的任何对象具有尽可能多的引用。一旦计数变为零,它将被释放。

The problem is that you are holding an array of strong pointers to view controllers as a cache. If you want them released, you have to manually nil those pointers. You are somehow pre-loading controllers into an array. They will stay alive until you unload them.

问题是你持有一组强指针来查看控制器作为缓存。如果你想要它们发布,你必须手动nil这些指针。您以某种方式将控制器预加载到阵列中。他们会活着,直到你卸下它们。

So, as long as you have a strong pointer to something, it will stay around.

所以,只要你有一个强大的指针指向某个东西,它就会保持不变。

#2


1  

Jody's edit, specifically mentioning setting pointers to nil, is what got the ball rolling for me in terms of understanding, and in the end I was able to figure out my problem by setting certain pointers to nil when my "viewControllerB" disappeared. Along the way, however, I also realized another important point - large images in core data are a huge memory burden, and in iOS 5, this can be remedied by setting an option to allow for external storage. So for anyone else who's a relative beginner like me and might come across a similar memory problem, this is a key way to limit the amount of memory being eaten by managed objects storing large amounts of data - your images (or whatever large amount of data) are saved to file automatically, without you having to do anything different in code.

Jody的编辑,特别提到设置指向nil的指针,就是在理解方面让我滚动的原因,最后我通过在我的“viewControllerB”消失时设置指向nil的指针来解决我的问题。然而,在此过程中,我还意识到另一个重点 - 核心数据中的大图像是巨大的内存负担,而在iOS 5中,可以通过设置允许外部存储的选项来解决这个问题。因此,对于像我这样的初学者而且可能遇到类似内存问题的其他人来说,这是限制存储大量数据的托管对象所占用的内存量的关键方法 - 您的图像(或任何大量数据) )自动保存到文件,而不必在代码中做任何不同的事情。