1

I have a memory leak that seems to be coming from a retain cycle. The memory allocation size is increasing every time this code runs:

- (void)nextPhoto {
    self.photoIndex++;
    if (self.photoIndex >= [self.photos count]) {
        self.photoIndex = 0;
    }
    __weak Photo *photo = [self.photos objectAtIndex:self.photoIndex];
    [[SDWebImageManager sharedManager] downloadImageWithURL:[NSURL URLWithString:photo.thumbnailURLString] options:SDWebImageRetryFailed progress:nil
                                              completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {

                                              }];
}

The code is looping on a 2 second timer:

self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(nextPhoto) userInfo:nil repeats:YES];

The total memory use increases without bounds until I get a memory overuse event.

Why is this code causing a retain cycle? Is there a special way I need to handle self in this situation?

self.photos is an NSMutableArray

self.photoIndex is an NSInteger

SDWebImageManager is a well maintained library: https://github.com/rs/SDWebImage and I use it in numerous other locations with no issues

Cbas
  • 6,003
  • 11
  • 56
  • 87
  • Have you tried to move `[SDWebImageManager sharedManager]` in a property? And, can you post the code inside the completion block? – Marco Santarossa Aug 10 '16 at 10:51
  • Why are start downloading image from 0 index again instead of stoping to download after all the images downloaded, also timer will call this method sync after every timeinterval, your image will not be download sometime if net speed is slow, within that interval. – Nirav D Aug 10 '16 at 11:28
  • @SaintThread I removed all the code from the completion block and it still causes the memory leak – Cbas Aug 10 '16 at 17:21
  • @Ndoc SDWebImageManager works as a downloader and cache, so if it comes across a duplicate url, it returns the cached copy – Cbas Aug 10 '16 at 17:22
  • I am quite sure that is not the solution, but: did you try putting this function in an autorelease pool block? – Marco Santarossa Aug 10 '16 at 17:28

2 Answers2

1

I don't see any problem involving a retain cycle here, even if you use self in the completion block. the block owner is SDWebImageManager so no problems here. a retain cycle could occur if you store your block in a property of your viewController, cause it then would own a block that retains it... It's not what is happening here imho.

Now your problem, i presume, comes from the UIImage. I depends of what you do in the block of course but if your storing the images then, yes every 2 seconds a new one is created and then it will fail eventually. You should keep a cache of images that has already been downloaded and try to download them only if needed... Add a NSDictionary with url as key and UIImage as value for example, this way you will only download your images once.

Florian Burel
  • 3,408
  • 1
  • 19
  • 20
  • There is no code in the completion block. Also, SDWebImageManager handles the caching already – Cbas Aug 10 '16 at 17:23
0

Ok I should have slept on this one... The function is actually working exactly as it should and it was self.photos that was increasing without bounds. Putting a limit on the size of that array fixed the "leak".

Cbas
  • 6,003
  • 11
  • 56
  • 87