Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capture self in block (retain cycles), not always?

The following code is from the LazyTableImages sample code provided by Apple (source here).

In their completion block they have a reference to self which should cause a retain cycle... But I don't get a warning for this in Xcode whereas in similar code of mine I would.

Is this correct?

Perhaps I'm missing a subtlety of this.

- (void)startIconDownload:(AppRecord *)appRecord forIndexPath:(NSIndexPath *)indexPath
{
    IconDownloader *iconDownloader = [self.imageDownloadsInProgress objectForKey:indexPath];
    if (iconDownloader == nil) 
    {
        iconDownloader = [[IconDownloader alloc] init];
        iconDownloader.appRecord = appRecord;
        [iconDownloader setCompletionHandler:^{

            UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];

            // Display the newly loaded image
            cell.imageView.image = appRecord.appIcon;

            // Remove the IconDownloader from the in progress list.
            // This will result in it being deallocated.
            [self.imageDownloadsInProgress removeObjectForKey:indexPath];

        }];
        [self.imageDownloadsInProgress setObject:iconDownloader forKey:indexPath];
        [iconDownloader startDownload];  
    }
}
like image 552
Daniel Avatar asked Jul 27 '13 18:07

Daniel


1 Answers

The retain cycle that you think you are seeing is because the object holds the the downloader in a dictionary.

It's true that there is a strong reference to self in the block, but, as long as the completion handler is always run, the downloader will be removed from the dictionary. And eventually this dictionary will be empty, which means there will be no objects holding on to self, and thus no retain cycle.

like image 51
Abizern Avatar answered Nov 15 '22 04:11

Abizern