Summary
A retain cycle (ROOT_CYCLE) was detected in CachedAnnouncementsStore using xctestleaks, a tool that injects a dylib shim and runs leaks(1) after each XCTest case.
Leak details
| Field |
Value |
| Class |
CachedAnnouncementsStore |
| Type |
ROOT_CYCLE |
| Instances |
12 |
| Total size |
1.05 KB |
| Triggering test |
-[AppIconListViewModelTests testAtLeastOneCustomIcon] |
Retain cycle chain
12 (1.05K) ROOT CYCLE: <CachedAnnouncementsStore> [144 bytes]
└─ 5 (288 bytes) __strong changeDispatcher
└─ ROOT CYCLE: <WordPressFlux.Dispatcher<()>> [32 bytes]
└─ 4 (256 bytes) __strong observers._variant
└─ ROOT CYCLE: <Swift._DictionaryStorage<WordPressFlux.DispatchToken, (()) -> ()>> [144 bytes]
CachedAnnouncementsStore holds a strong reference to a WordPressFlux.Dispatcher<()> via changeDispatcher. That dispatcher retains its observers dictionary strongly, which closes the cycle and prevents deallocation.
Impact
- 12 leaked instances, 1.05 KB per test run
- Any test that instantiates
CachedAnnouncementsStore and registers observers without explicitly removing them will retain these objects indefinitely
How to reproduce
XCTestLeaks integrates itself with unit tests and get any existing leaks:
xctestleaks agent run \
--project WordPress/WordPress.xcodeproj \
--scheme "WordPress" \
--destination "platform=iOS Simulator,name=iPhone 16"
Check xctestleaks-artifacts/leaks/CachedAnnouncementsStore/ for the full raw leaks(1) output.
Suggested fix
Either:
- Hold
changeDispatcher as weak var in CachedAnnouncementsStore, or
- Unregister the observer in
deinit to break the cycle explicitly
Detected with xctestleaks
Summary
A retain cycle (ROOT_CYCLE) was detected in
CachedAnnouncementsStoreusing xctestleaks, a tool that injects a dylib shim and runsleaks(1)after each XCTest case.Leak details
CachedAnnouncementsStore-[AppIconListViewModelTests testAtLeastOneCustomIcon]Retain cycle chain
CachedAnnouncementsStoreholds a strong reference to aWordPressFlux.Dispatcher<()>viachangeDispatcher. That dispatcher retains itsobserversdictionary strongly, which closes the cycle and prevents deallocation.Impact
CachedAnnouncementsStoreand registers observers without explicitly removing them will retain these objects indefinitelyHow to reproduce
XCTestLeaks integrates itself with unit tests and get any existing leaks:
Check
xctestleaks-artifacts/leaks/CachedAnnouncementsStore/for the full rawleaks(1)output.Suggested fix
Either:
changeDispatcherasweak varinCachedAnnouncementsStore, ordeinitto break the cycle explicitlyDetected with xctestleaks