Capturing yourself in a block (hold cycles) is not always the case?

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

In their completion block, they have a reference to self, which should cause a save loop ... But I do not get a warning for this in Xcode, whereas in a similar code I would do it.

Is it correct?

Perhaps I lack the subtleties 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]; } } 
+6
source share
4 answers

The save cycle, which, in your opinion, you see, is connected with the fact that the object stores the loader in the dictionary.

It is true that the block has a strong reference to self, but as long as the completion handler always starts, the bootloader will be removed from the dictionary. And, in the end, this dictionary will be empty, which means that objects will not hold themselves, and therefore there will be no save cycle.

+4
source

self does not have a strong pointer to iconDownloader . It is created and attached to this method:

 IconDownloader *iconDownloader = [self.imageDownloadsInProgress objectForKey:indexPath]; 

If iconDownloader was a strong property ( self.iconDownloader ), then Xcode would detect a strong reference loop.

0
source

Capturing oneself is not a conservation cycle. This is the only link. One link cannot build a loop. The usual antipattern is an addition, the link to the block is stored in a strong property of itself. Than two links create a loop.

0
source

There are no warnings because the compiler is not yet able to detect all possible save cycles.

For instance:

 - (void)foo { _block = ^ { [self done]; }; // Warning: Possible retain cycle DSGenericBlock foo = ^ { [self done] }; _block = foo; // No warning. } 

If you need to assign the block directly to the instance variable "self", you will receive a warning about the possible saving of the loop. Instead, the block is assigned to another object, which is then saved by itself, so the compiler does not detect a loop (even if the loop exists).

0
source

Source: https://habr.com/ru/post/950430/


All Articles