weak variable with a strong reference in a block: does not create a retain cycle?

781 views Asked by At

why does it work when we pass the weak reference to a strong reference inside the block? If a local variable in a block is retained, this should add a retain to self and thus create this bad retain cycle?

Here is the example :

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

There are 2 answers

0
MANIAK_dobrii On BEST ANSWER

When you create or copy a block (it could be copied when you, for example, schedule it to gcd), referenced variables are captured (unless declared with __block specifier). Strong references are retained, weak references are not.

When you create local strongSelf variable it keeps self alive while block executes (i.e. while it's not executed and sits in a property there's no strong reference). When you reference self directly - self is captured and retained, now it keeps self while block is alive.

__weak id weakSelf = self; 
[self.operationQueue addOperationWithBlock:^{
    NSNumber* result = findLargestMersennePrime();
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 

        MyClass* strongSelf = weakSelf; // strong reference when block executes
        [self foo]; // strong reference when block created/copied

        strongSelf.textLabel.text = [result stringValue];
    }]; 
}];

See the difference? If you kill all strong pointers to object with direct self reference there is still one strong reference inside the block, the one which was captured and retained. At the same time local strongSelf pointer only holds strong reference to self while block is executed, so, if self was already dead, weakSelf would be nil and strongSelf will get nil value.

0
Daij-Djan On

no it doesn't create a cycle since self isn't captured as strong! :)

strongSelf is a strong reference that retains self BUT since strongSelf is a local var, it is released when the block is done and the retain count drops fine