If you have code for this form:
object.block = ^{
object
save or copy the block that you pass to it. But the block itself will also save the object
, because it is strictly referenced from within the block. This is a save cycle. Even after the block has completed execution, the reference loop still exists, and neither the object nor the block can be freed. Remember that a block can be called several times, so it cannot just forget all the variables that it refers after it has finished executing once.
To break this loop, you can define object
as a __block
variable, which allows you to change its value from within the block, for example. changing it to nil
to break the loop:
__block id object = ...; object.block = ^{
When we assign object
- nil
at the end of a block, the block will no longer save object
, and the save cycle will be broken. This allows you to free both objects.
One specific example of this is the NSOperation
completionBlock
property. If you use completionBlock
to access the result of the operation, you need to break the save loop that was created:
__block NSOperation *op = [self operationForProcessingSomeData]; op.completionBlock = ^{ // since we strongly reference op here, a retain cycle is created [self operationFinishedWithData:op.processedData]; // break the retain cycle! op = nil; }
As described in the documentation, there are a number of other methods that you can also use to break these save cycles. For example, you will need to use a different technique in code other than ARC than in ARC code.
source share