Breaking ARC Retain Cycle in Objective-C Blocks
In a recent client project, we noticed its iOS app often received low memory
warnings. The iOS app is developed with ARC-enabled (Automatic Reference Counting).
When profiling the app using Instruments > Allocations, we found that a lot of unused ViewController objects were not being released from memory.
In this example code, the controller object holds a strong reference to a
When object A points strongly to object B, and B points strongly to A, a retain cycle is created, and both objects cannot be released from memory.
If your app is targeted for iOS 5, you can use the
Because we are using the
When profiling the app using Instruments > Allocations, we found that a lot of unused ViewController objects were not being released from memory.
Retain Cycle
The codebase uses a lot of Objective-C blocks as shown below, andself
is often being called within the blocks:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
In this example code, the controller object holds a strong reference to a
doneButton
object. But because the doneButton onTouch:
block is referencing
self
, now the button object holds a strong reference back to the controller
object.When object A points strongly to object B, and B points strongly to A, a retain cycle is created, and both objects cannot be released from memory.
Use Lifetime Qualifiers
Apple Developer’s guide on ARC transition suggested a few ways to break the retain cycle using different lifetime qualifiers. It is definitely a must read for iOS development.If your app is targeted for iOS 5, you can use the
__weak
lifetime qualifier to break the cycle:1 2 3 4 5 6 7 8 9 10 |
|
Because we are using the
__weak
qualifier here, the doneButton onTouch:
block
only has a weak reference to the controller object. Now, the controller
object will be released from memory when its reference count drops to 0.