UIImageView/UIImage “Memory Tag 70” release timing

2019-02-07 15:01发布

问题:

I have a long horizontal paged scrollview, for each page, I put a fullscreen UIImage.

As it is expensive and not necessary to add all UIImage at once, currently I lazy load the images (pageIndex-1 + pageIndex + pageIndex+1 's images, using NSOperationQueue FYI), and remove all other UIImageViews.

The memory usage reported from Instrument is acceptable with normal usage, but I discover if I keep scrolling (switching between 30 pages continously), the Dirty memory would keep increasing, especially "Memory Tag 70" which I believe it is the raw data from UIImage. Once I stop touching the app for 3~4 seconds, ALL "Memory Tag 70" would be released automagically.

I've put NSLog in several places and I'm sure the UIImageViews are removed from its superview when it is out of the "display range".

Is scrolling preventing the main loop to release those memory? What could I do to prevent such condition? Thanks!

p.s The huge drop in Dirty Size is the moment when I stop scrolling.

回答1:

(Just a guess, I'm far from an Xcode to test it, and assuming a non-ARC environment)

Instead of [otherImageView removeFromSuperview], you can use

UIImage *image = [otherImageView.image retain];
otherImageView.image = nil;
[image release]; // the image won't go to the main autorelease pool
[otherImageView removeFromSuperview]; // No one has references to otherImageView, so it goes to the autorelease pool

To avoid the image going to the autorelease pool.



回答2:

I would try the following:

  1. Don't use [UIImage imageNamed:] for loading images. That builds up in memory tag 70.
  2. Use the instance methods initWithContentsOfFile: and autorelease it explicitly. Note: Doing so would mean losing the caching advantage [UIImage imageNamed:] gives. But try it out.
  3. Use @autoreleasepool (instead of NSAutoreleasePool) around the code where image allocation happens. It can be used regardless of ARC.


回答3:

From your graph it appears the memory consumption levels off, which is consistent with the images being cached and then released when the scroll stops (perhaps throughg an internal autorelease in the scrollview). That caching and memory buildup is probably making your scrolling smoother. If you really need to prevent memory build up then you will need to alloc and release the images manually yourself (echoing AnlmlsH's suggestion of forgoing imageNamed).

But eliminating caching may result in jerkly scrolling....classic time/space tradeoff, and you need to determine which one is more important for your app's case.