简体   繁体   中英

SDWebImage - Memory leak in UITableView?

I'm sorry in advance as maybe this is a dumb and noob question...

I'm using SDWebImage to display pictures in a UITableView in my cellForRowAtIndexPath method, using the classic

[cell.pointPicture setImageWithURL:[NSURL URLWithString:thePoint.imageURL] placeholderImage:[UIImage imageNamed:POINT_DEFAULT_IMAGE]];

(the displayed pictures are light and well compressed jpgs, just some ko, and yes I'm using dequeueReusableCellWithIdentifier of course).

When I inspect my app with " Instrument - Allocations ", and just scroll down my UITableView (with 40 cells containing picture, a bit like Instagram), I got a huge amount of memory used ! (see screenshot)

仪器分配截图

But it seems to be " VM ", and especially " VM: CG raster data " from the coreGraphics library.

So the questions are :

  • Is it normal?
  • Is that a serious problem?
  • Is there a way to avoid this?

I'm sorry but after few search on the web I can't find any relevant information concerning the " VM: CG raster data "... Any idea? Thanks in advance !

I experienced the same issue and found the root cause, at least in my implementation.

Root Cause

The root cause was that my table cell stored a strong pointer to the image which is stored in SDWebImage cache. This strong pointer, caused the memory release function of SDWebImage removeAllObjects not to release any memory when receiving a memory warning from iOS.

Solution 1 - Keep weak pointers from within your ViewController and allow only SDWebImage to keep a strong pointer to all UIImage objects.

Solution 2 - Implement - (void)prepareForReuse and set the image pointers to nil

To test this solution run your application and simulate a memory warning - You will be able to see the data removed

As explained to me by someone working on SDWebImage :

SDWebImage cache images is using NSCache . It is discardable memory. See Apple documentation , so this is a perfectly normal behavior and the memory is released if needed.

I had the same issue. My problem seemed to originate from something else than the SDWebImage cache but since it did contribute to the memory buildup, the first thing I though was that the cache could be the cause of my problem. But it wasn't. It could be you have the same kind of issue. Keep in mind that I am using ARC.

  • Run the profiler with the Leaks template and check for the allocation of your own classes in the Allocation Summary .
  • Dive into them and check how they are allocated, if there are leaks. Mind that a leak doesn't show up in the Leaks instrument because you are using ARC. So Instruments could think everything is going oké but there still could be a leak somewhere. By diving in to the allocation of your own classes you could figure out what is going wrong.
  • Keep in mind that the retain/release count information is only provided when using the Leaks template and not while using the Allocations template.

My problem was that I was referencing instance variables and self directly from within blocks without reassigning them to __weak variables. When self is used within a block it will automatically be retained by ARC and sometimes never released. A weak reference prevents that from happening.

For example, this is wrong :

[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardDidShowNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
    [self.view setContentOffset:CGPointMake(0.0, kKeyboardOffset) animated:YES];
}];

You should call self using a __weak reference like this:

__weak YourViewControllerClass *weakSelf = self;
[[NSNotificationCenter defaultCenter] addObserverForName:UIKeyboardDidShowNotification object:nil queue:nil usingBlock:^(NSNotification *note) {
    [weakSelf.view setContentOffset:CGPointMake(0.0, kKeyboardOffset) animated:YES];
}];

Since my app uses a lot of block's I had a ton of leaks the Leaks instrument could not detect. When I fixed them the memory problem was gone.

I hope this helps.

Although NSCache will free memory on low memory system notifications also more critical (and way smaller in memory footprint) objects will get discarded in other parts of the program.

It would be better to set the library's maxMemoryCost (which sets the NSCache totalCostLimit ) to a limit to prevent SDWebImage from triggering memory notifications.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM