Question

While reading a blog about concurrency in iOS, I stumbled upon the next code:

__weak id weakSelf = self;
[self.operationQueue addOperationWithBlock:^{
    NSNumber* result = findLargestMersennePrime();
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        MyClass* strongSelf = weakSelf;
        strongSelf.textLabel.text = [result stringValue];
    }];
}];

The author explains that the use of weakref is needed since:

we need to make a weak reference to self, otherwise we create a retain cycle (the block retains self, the private operation queue retains the block, and self retains the operation queue). Within the block we convert it back to a strong reference to make sure it doesn’t get deallocated while running the block.

I can understand why the block would have retained self, but I don't understand why (and where exactly) the private operation queue retains the block and when/where self retaind the opeation queue. Any explanation would be much appreciated.

Was it helpful?

Solution

try to write this code without weak reference:

[self.operationQueue addOperationWithBlock:^{
    NSNumber* result = findLargestMersennePrime();
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        self.textLabel.text = [result stringValue];
    }];
}];

to make this code work - compiler retains reference to self in operationQueue to avoid situation when self is deleted from memory and self.textLabel.text = .. is executed, so it tries to guarantee that object will be alive.

This is where cycle is actually created:

  1. self retains operationQueue (this means that operationQueue cannot be deleted while self is alive)
  2. operationQueue retains self (this means that self cannot be deleted while operationQueue is alive)

to avoid this - you're creating week reference, so you're eliminating 2nd retention

PS. "block" is part of operationQueue, so we can assume just 2 items in this scheme.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top