Read XcodeToolingCheatSheet.md (Run scheme and diagnostics, Debugger UI) if Zombie Objects or the stopped-debugger views are unfamiliar.
Post-MVP / scheme diagnostic. Use Zombie Objects when a crash feels like use-after-free or a late callback after teardown, but the default trap or EXC_BAD_ACCESS text is too vague to act on.
Source of truth: SignalLab/SignalLab/Shared/LabDomain/LabCatalog.swift (zombieObjectsLab)
How do I turn an unclear memory crash into a direct "you messaged a dead object" diagnosis?
- Crash or trap after a screen, helper, or owner should be gone.
- Often involves notifications, closures, timers, or async completion after
deinit.
Xcode Run → Diagnostics → Zombie Objects (exact label may vary by Xcode version).
| Topic | Use instead |
|---|---|
| Object stays alive after dismiss | Retain Cycle Lab + Memory Graph |
| Main thread frozen | Hang Lab |
| Concurrent unsynchronized access | Thread Sanitizer Lab |
- Open Zombie Objects Lab and tap Run scenario from Xcode. The scenario sends a message to a deallocated Objective-C object. Optionally run once without Zombies first to feel the vaguer stop.
- Enable Zombie Objects in Run → Diagnostics, relaunch from Xcode, and tap Run scenario again.
- Read the new diagnostic: class name, zombie wording, or deallocated-instance hint.
- Find the late code path (callback, observer, weak-vs-strong mistake) that ran after release.
- Fix real projects (invalidate,
weak, tear down subscription, extend lifetime intentionally) and disable Zombies when done.
- Zombies enabled for the run that reproduced the bug.
- You can contrast the crash text with Zombies on vs off.
- You can explain why this is not Retain Cycle Lab's "still alive" symptom.