iOS Chaos Monkey — Crash-Hunter Best Practices
Adversarial crash-hunting guide for iOS and Swift applications. Contains 47 rules across 8 categories, prioritized by crash severity. Every rule follows TDD: dangerous code first, a failing test that proves the bug, then the fix that makes the test pass.
Clinic Architecture Contract (iOS 26 / Swift 6.2)
All guidance in this skill assumes the clinic modular MVVM-C architecture:
- Feature modules import Domain
- DesignSystem only (never Data , never sibling features)
-
App target is the convergence point and owns DependencyContainer , concrete coordinators, and Route Shell wiring
-
Domain stays pure Swift and defines models plus repository, *Coordinating , ErrorRouting , and AppError contracts
-
Data owns SwiftData/network/sync/retry/background I/O and implements Domain protocols
-
Read/write flow defaults to stale-while-revalidate reads and optimistic queued writes
-
ViewModels call repository protocols directly (no default use-case/interactor layer)
When to Apply
Reference these guidelines when:
-
Hunting data races, deadlocks, and concurrency crashes in Swift
-
Auditing memory management for retain cycles and use-after-free
-
Reviewing async/await code for cancellation and continuation leaks
-
Stress-testing file I/O and CoreData/SwiftData persistence layers
-
Writing proof-of-crash tests before implementing fixes
Rule Categories by Priority
Priority Category Impact Prefix
1 Data Races & Thread Safety CRITICAL race-
2 Memory Corruption & Leaks CRITICAL mem-
3 Deadlocks & Thread Starvation HIGH dead-
4 Async/Await & Structured Concurrency HIGH async-
5 File I/O & Persistence Corruption MEDIUM-HIGH io-
6 Collection & State Mutation MEDIUM mut-
7 Resource Exhaustion MEDIUM exhaust-
8 Objective-C Interop Traps LOW-MEDIUM objc-
Quick Reference
- Data Races & Thread Safety (CRITICAL)
-
race-dictionary-concurrent-write
-
Concurrent Dictionary mutation crashes with EXC_BAD_ACCESS
-
race-array-concurrent-append
-
Concurrent Array append corrupts internal buffer
-
race-property-access
-
Unsynchronized property read-write across threads
-
race-lazy-initialization
-
Lazy property double-initialization under concurrency
-
race-singleton-initialization
-
Non-atomic singleton exposes partially constructed state
-
race-bool-flag
-
Non-atomic Bool flag creates check-then-act race
-
race-closure-capture-mutation
-
Closure captures mutable reference across threads
-
race-delegate-nilification
-
Delegate set to nil during active callback
- Memory Corruption & Leaks (CRITICAL)
-
mem-closure-retain-cycle
-
Strong self capture in escaping closures creates retain cycle
-
mem-timer-retain-cycle
-
Timer retains target creating undiscoverable retain cycle
-
mem-delegate-strong-reference
-
Strong delegate reference prevents deallocation
-
mem-unowned-crash
-
Unowned reference crashes after owner deallocation
-
mem-notification-observer-leak
-
NotificationCenter observer retains closure after removal needed
-
mem-combine-sink-retain
-
Combine sink retains self without cancellable storage
-
mem-async-task-self-capture
-
Task captures self extending lifetime beyond expected scope
- Deadlocks & Thread Starvation (HIGH)
-
dead-sync-on-main
-
DispatchQueue.main.sync from main thread deadlocks instantly
-
dead-recursive-lock
-
Recursive lock acquisition on same serial queue
-
dead-actor-reentrancy
-
Actor reentrancy produces unexpected interleaving
-
dead-semaphore-in-async
-
Semaphore.wait() inside async context deadlocks thread pool
-
dead-queue-hierarchy
-
Dispatch queue target hierarchy inversion deadlocks
-
dead-mainactor-blocking
-
Blocking MainActor with synchronous heavy work
- Async/Await & Structured Concurrency (HIGH)
-
async-missing-cancellation
-
Missing Task.isCancelled check wastes resources after navigation
-
async-detached-task-leak
-
Detached task without cancellation handle leaks work
-
async-task-group-error
-
TaskGroup silently drops child task errors
-
async-continuation-leak
-
CheckedContinuation never resumed leaks awaiting task
-
async-actor-hop-starvation
-
Excessive MainActor hops in hot loop starve UI updates
-
async-unsafe-sendable
-
@unchecked Sendable hides data race from compiler
- File I/O & Persistence Corruption (MEDIUM-HIGH)
-
io-concurrent-file-write
-
Concurrent file writes corrupt data without coordination
-
io-coredata-cross-thread
-
CoreData NSManagedObject accessed from wrong thread
-
io-swiftdata-background
-
SwiftData model accessed from wrong ModelContext
-
io-plist-concurrent-mutation
-
UserDefaults concurrent read-write produces stale values
-
io-filemanager-race
-
FileManager existence check then use is a TOCTOU race
-
io-keychain-thread-safety
-
Keychain access from multiple threads returns unexpected errors
- Collection & State Mutation (MEDIUM)
-
mut-enumerate-and-mutate
-
Collection mutation during enumeration crashes at runtime
-
mut-kvo-dealloc-crash
-
KVO observer not removed before deallocation crashes
-
mut-index-out-of-bounds
-
Array index access without bounds check crashes
-
mut-force-unwrap
-
Force unwrapping optional in production crashes on nil
-
mut-enum-future-cases
-
Non-exhaustive switch crashes on unknown enum case
- Resource Exhaustion (MEDIUM)
-
exhaust-unbounded-task-spawn
-
Unbounded task spawning in loop exhausts memory
-
exhaust-thread-explosion
-
GCD creates unbounded threads under concurrent load
-
exhaust-urlsession-leak
-
URLSession not invalidated leaks delegate and connections
-
exhaust-file-descriptor-leak
-
File handle not closed leaks file descriptors
-
exhaust-memory-warning-ignored
-
Low memory warning ignored triggers Jetsam kill
- Objective-C Interop Traps (LOW-MEDIUM)
-
objc-unrecognized-selector
-
Missing @objc annotation crashes with unrecognized selector
-
objc-nsnull-in-json
-
NSNull in decoded JSON collection crashes on access
-
objc-bridge-type-mismatch
-
Swift/ObjC bridge type mismatch crashes at runtime
-
objc-dynamic-dispatch
-
Missing dynamic keyword breaks method swizzling
How to Use
Read individual reference files for detailed explanations and code examples:
-
Section definitions - Category structure and impact levels
-
Rule template - Template for adding new rules
Reference Files
File Description
references/_sections.md Category definitions and ordering
assets/templates/_template.md Template for new rules
metadata.json Version and reference information