Breaking Retain Cycles in Objective-C ARC with __weak and __strong
How to break strong reference cycles in Objective-C blocks using the __weak-strong pattern to prevent memory leaks under ARC.
06 Feb 2026, 02:45 UTC

The Problem: Retain Cycles in Objective-C ARC Blocks
In Objective-C using Automatic Reference Counting (ARC), a retain cycle occurs when two objects hold strong references to each other. Because ARC only deallocates an object when its reference count reaches zero, these objects persist in memory indefinitely. This is most common when a block captures self strongly while self owns the block.
Useful takeaway: capture __weak self before a block, then assign __strong self = weakSelf inside the block to use a safe strong reference.
The Mechanism: How __weak Breaks the Cycle
ARC inserts retain and release calls at compile time. A __weak reference does not increment the retain count. When the referenced object is deallocated, ARC sets the __weak pointer to nil. This eliminates dangling pointers and breaks retain cycles.
The Weak-Strong Dance
When writing a block that might outlive the capturing object, follow this pattern:
__weak typeof(self) weakSelf = self;
[self.networkManager fetchDataWithCompletion:^(NSData *data, NSError *error) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf updateUIWithData:data];
}
}];The outer __weak breaks the cycle. Inside the block, __strong keeps self valid for the duration of the block's execution. If self is deallocated before the block runs, weakSelf is nil, strongSelf becomes nil, and the conditional safely exits.
Execution Details
- Where to run: within any Objective-C method (.m files) compiled with ARC that uses blocks or delegates.
- Permissions: none required; this is a language-level ARC pattern.
- Placeholders: self.networkManager, fetchDataWithCompletion, and updateUIWithData are examples; replace with your actual properties and methods.
- Expected result: when the containing object is dismissed, its reference count drops to zero. Pending blocks see weakSelf as nil and exit gracefully, preventing leaks.
Limits and Common Mistakes
- Capturing properties instead of self: writing
__weak typeof(self.someProperty) weakProp = self.somePropertyonly protects that property. If the block needs the full object, capture self. - Mixing ARC and manual reference counting: the
__weakqualifier is ARC-specific. Using it in a non-ARC-compiled file produces a compiler error. Do not manually retain or release a__weakvariable, and never mix manual retain/release calls into ARC code, which risks double-release crashes. - The strong-only trap: omitting
__weakand referencing self directly inside a block stored on self creates a permanent cycle: self → block → self. Neither object is ever released.
Verification and Diagnostics
- Dealloc logging: override
deallocand log a message. If the log appears when the object is dismissed, the cycle is broken. - Xcode Memory Graph: run the app, trigger the action, dismiss the object, then open the Debug Memory Graph. If the object persists with a highlighted reference cycle, the
__weakreference is missing or incorrect. - Instruments Leaks: profile with the Leaks instrument. A leaked object appears in the timeline; correct use of
__weakshould eliminate it.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.