---
# === IDENTITY ===
id: software/debugging/ios-crash-patterns/2026
canonical_question: "What are the most common iOS app crash patterns and fixes?"
aliases:
  - "iOS app crash debugging"
  - "EXC_BAD_ACCESS iOS fix"
  - "SIGABRT iOS crash"
  - "EXC_BREAKPOINT Swift crash"
  - "iOS watchdog termination 0x8badf00d"
  - "Swift force unwrap nil crash"
  - "iOS crash report analysis"
  - "Xcode crash log debugging"
  - "iOS jetsam memory crash"
  - "iOS crash symbolication"
entity_type: software_reference
domain: software > debugging > ios_crash_patterns
region: global
jurisdiction: global
temporal_scope: 2020-2026

# === VERIFICATION ===
last_verified: 2026-02-23
confidence: 0.92
version: 1.0
first_published: 2026-02-23

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: stable
  last_breaking_change: "Swift 6 strict concurrency checking (2024)"
  next_review: 2026-08-22
  change_sensitivity: low

# === CONSTRAINTS ===
constraints:
  - "iOS/iPadOS/watchOS/tvOS/visionOS only — Android crashes use different signals and tooling (logcat, tombstones)"
  - "Crash reports must be symbolicated before analysis — unsymbolicated reports show only hex addresses, not function names"
  - "dSYM files must match the exact build that crashed — mismatched dSYMs produce wrong or missing symbols"
  - "Watchdog terminations (0x8badf00d) do not produce crash reports in the normal sense — they are logged as termination events in Xcode Organizer"
  - "Never ship with Zombie Objects enabled — it prevents deallocation and causes unbounded memory growth in production"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "Android app crash or ANR (Application Not Responding)"
    use_instead: "Android crash debugging — uses logcat, tombstones, and different signal handling"
  - condition: "C/C++ segmentation fault on Linux/macOS (not iOS)"
    use_instead: "software/debugging/c-cpp-segfault/2026"
  - condition: "React Native or Flutter crash on iOS"
    use_instead: "Cross-platform framework crash debugging — JS/Dart exceptions need framework-specific tools before native analysis"
  - condition: "App rejected by App Review for crashes"
    use_instead: "App Store review crash resolution — focus on TestFlight Xcode Organizer crash triage"

# === AGENT HINTS ===
inputs_needed:
  - key: "crash_type"
    question: "What exception type do you see in the crash report?"
    type: choice
    options: ["EXC_BAD_ACCESS", "EXC_CRASH (SIGABRT)", "EXC_BREAKPOINT (SIGTRAP)", "EXC_RESOURCE", "Watchdog (0x8badf00d)", "Jetsam/OOM", "Unknown"]
  - key: "language"
    question: "Is the crashing code Swift or Objective-C?"
    type: choice
    options: ["Swift", "Objective-C", "Mixed", "Unknown"]
  - key: "ios_version"
    question: "What iOS version is the crash occurring on?"
    type: choice
    options: ["iOS 18+", "iOS 17", "iOS 16", "iOS 15 or earlier", "Multiple versions"]

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/software/debugging/ios-crash-patterns/2026"
suggested_citation: "Source: knowledgelib.io — AI Knowledge Library (verified 2026-02-23)"

# === RELATED UNITS ===
related_kos:
  related_to:
    - id: "software/debugging/c-cpp-segfault/2026"
      label: "C/C++ Segfault Debugging (underlying memory model)"
    - id: "software/debugging/xcode-instruments-guide/2026"
      label: "Xcode Instruments Profiling Guide"
  solves:
    - id: "software/debugging/swift-concurrency-crashes/2026"
      label: "Swift Concurrency Data Race Crashes"
  often_confused_with:
    - id: "software/debugging/ios-performance-hangs/2026"
      label: "iOS Performance Hangs (no crash — app freezes but does not terminate via exception)"

# === SOURCES (7 authoritative sources) ===
sources:
  - id: src1
    title: "Identifying the Cause of Common Crashes"
    author: Apple
    url: https://developer.apple.com/documentation/xcode/identifying-the-cause-of-common-crashes
    type: official_docs
    published: 2024-06-10
    reliability: authoritative
  - id: src2
    title: "Understanding the Exception Types in a Crash Report"
    author: Apple
    url: https://developer.apple.com/documentation/xcode/understanding-the-exception-types-in-a-crash-report
    type: official_docs
    published: 2024-06-10
    reliability: authoritative
  - id: src3
    title: "Addressing Watchdog Terminations"
    author: Apple
    url: https://developer.apple.com/documentation/xcode/addressing-watchdog-terminations
    type: official_docs
    published: 2024-06-10
    reliability: authoritative
  - id: src4
    title: "Understanding Crashes and Crash Logs (WWDC18 Session 414)"
    author: Apple
    url: https://developer.apple.com/videos/play/wwdc2018/414/
    type: official_docs
    published: 2018-06-04
    reliability: authoritative
  - id: src5
    title: "EXC_BAD_ACCESS Crash Error: Understanding and Solving It"
    author: Antoine van der Lee (SwiftLee)
    url: https://www.avanderlee.com/swift/exc-bad-access-crash/
    type: technical_blog
    published: 2024-03-15
    reliability: high
  - id: src6
    title: "Why Does My iOS App Crash? The 10 Most Common Causes"
    author: Chandra Welim
    url: https://medium.com/@chandra.welim/why-does-my-ios-app-crash-the-10-most-common-causes-b526cc318f52
    type: technical_blog
    published: 2025-12-01
    reliability: moderate_high
  - id: src7
    title: "Identifying High-Memory Use with Jetsam Event Reports"
    author: Apple
    url: https://developer.apple.com/documentation/xcode/identifying-high-memory-use-with-jetsam-event-reports
    type: official_docs
    published: 2024-06-10
    reliability: authoritative
---

# What Are the Most Common iOS App Crash Patterns and Fixes?

## TL;DR

- **Bottom line**: ~80% of iOS crashes fall into 10 patterns: force-unwrap nil, unrecognized selector, array out-of-bounds, EXC_BAD_ACCESS (zombie/dangling pointer), watchdog kill (0x8badf00d), jetsam OOM, Swift type cast failure, threading violation, stack overflow, and missing weak delegate. Each has a distinct exception type and a deterministic fix.
- **Key tool/command**: `xcrun atos -arch arm64 -o MyApp.app.dSYM/Contents/Resources/DWARF/MyApp -l 0x100000000 0x100012345`
- **Watch out for**: Unsymbolicated crash reports — without dSYMs, the stack trace is hex addresses. Always archive dSYMs with every release.
- **Works with**: Xcode 15+, iOS 15-18, Swift 5.9-6.0, Objective-C. Tools: Xcode Organizer, lldb, Instruments, MetricKit.

## Constraints
<!-- Agents: read this section before recommending any action from this unit.
     These are hard constraints that must not be violated. -->

- **Always symbolicate before analyzing** — raw crash addresses are meaningless without the matching dSYM. Use `atos` or Xcode Organizer for symbolication. [src1, src4]
- **Never enable Zombie Objects in production builds** — NSZombie prevents deallocation, causing unbounded memory growth. Use only in Debug scheme diagnostics. [src5]
- **Watchdog timeouts are not crashes** — they are process terminations by the OS. The crash report format differs (termination reason, not exception type). [src3]
- **Thread Sanitizer and Address Sanitizer cannot run simultaneously** — enable one at a time in Xcode Scheme > Diagnostics. [src4]
- **dSYM must match the exact binary UUID** — even a single source change produces a different UUID. Archive dSYMs for every build you distribute. [src1, src4]

## Quick Reference

| # | Crash Pattern | Likelihood | Exception Type / Signature | Fix |
|---|---|---|---|---|
| 1 | Force-unwrap nil optional | ~20% of Swift crashes | `EXC_BREAKPOINT (SIGTRAP)` — `Fatal error: Unexpectedly found nil while unwrapping an Optional value` | Replace `!` with `guard let`, `if let`, or `??` default value [src2, src6] |
| 2 | Unrecognized selector sent | ~15% of cases | `EXC_CRASH (SIGABRT)` — `-[NSObject doesNotRecognizeSelector:]` in backtrace | Check IBOutlet connections; verify protocol conformance; use `responds(to:)` before calling [src1, src6] |
| 3 | Array/collection index out of bounds | ~12% of cases | `EXC_CRASH (SIGABRT)` — `Fatal error: Index out of range` | Bounds-check with `.indices.contains(i)` or use `.first`, `.last` safe accessors [src1, src6] |
| 4 | EXC_BAD_ACCESS (zombie/dangling pointer) | ~10% of cases | `EXC_BAD_ACCESS (SIGSEGV)` — `KERN_INVALID_ADDRESS` at `objc_msgSend` | Enable Zombie Objects in Debug; check for `unowned` references to deallocated objects; use `weak` instead [src2, src5] |
| 5 | Watchdog termination (0x8badf00d) | ~10% of cases | Termination Reason: `FRONTBOARD` — `8badf00d` (scene-update or launch timeout) | Move all blocking work off the main thread; app launch must complete in <20s, resume in <10s [src3] |
| 6 | Jetsam / out-of-memory (OOM) | ~8% of cases | Termination Reason: `Namespace JETSAM` — `per-process-limit` or `vm-pageshortage` | Reduce memory footprint; downsample images; use `autoreleasepool` in loops; respond to `didReceiveMemoryWarning` [src7] |
| 7 | Failed type cast (`as!`) | ~7% of Swift crashes | `EXC_BREAKPOINT (SIGTRAP)` — `Could not cast value of type 'X' to 'Y'` | Use `as?` conditional cast instead of `as!` forced cast [src2, src6] |
| 8 | Main thread UI violation | ~5% of cases | `EXC_BREAKPOINT` from Main Thread Checker — `UI API called on a background thread` | Wrap UI updates in `DispatchQueue.main.async {}` or use `@MainActor` [src1, src6] |
| 9 | Stack overflow (deep recursion) | ~3% of cases | `EXC_BAD_ACCESS (SIGSEGV)` — crash address near thread stack guard page | Add recursion base case; convert deep recursion to iteration; increase stack size for worker threads [src2] |
| 10 | Missing weak delegate / notification observer | ~3% of cases | `EXC_BAD_ACCESS` — crash in `objc_msgSend` when sending to deallocated delegate | Declare delegates as `weak var`; remove notification observers in `deinit` [src5, src6] |
| 11 | KVO observer not removed | ~2% of cases | `EXC_CRASH (SIGABRT)` — `An instance was deallocated while key value observers were still registered` | Remove all KVO observers in `deinit` or use `NSKeyValueObservation` token pattern [src1] |
| 12 | Core Data concurrency violation | ~2% of cases | `EXC_BAD_INSTRUCTION` or `EXC_BAD_ACCESS` inside Core Data stack | Use `perform {}` / `performAndWait {}` on NSManagedObjectContext; never pass NSManagedObject across threads [src1, src4] |
| 13 | Swift concurrency data race (Swift 6) | ~2% of cases | `EXC_BREAKPOINT` — runtime exclusivity violation or Sendable conformance failure | Enable strict concurrency checking; mark shared state as `@Sendable` or use actors [src2] |

## Decision Tree

> Full script: [decision-tree.txt](scripts/decision-tree.txt) (26 lines)

```
START — iOS app crashed
├── Do you have a symbolicated crash report?
│   ├── YES → Read Exception Type field
│   │   ├── EXC_BREAKPOINT (SIGTRAP)?
│   │   │   ├── "Unexpectedly found nil" → Cause #1: Force-unwrap nil
# ... (see full script)
```

## Step-by-Step Guide

### 1. Acquire and symbolicate the crash report

Crash reports are useless without symbolication. Xcode Organizer auto-symbolicates if you archived the build with dSYMs. [src1, src4]

```bash
# Manual symbolication with atos
xcrun atos -arch arm64 \
  -o MyApp.app.dSYM/Contents/Resources/DWARF/MyApp \
  -l 0x100a40000 \
  0x100a56789

# Output: -[ViewController viewDidLoad] (in MyApp) (ViewController.swift:42)

# Verify dSYM matches binary UUID
dwarfdump --uuid MyApp.app.dSYM
dwarfdump --uuid MyApp.app/MyApp
# Both should print the same UUID
```

**Verify**: `atos` output shows function names and line numbers, not hex addresses.

### 2. Read the exception type and termination reason

The exception type tells you the crash category. Read the crash report header. [src2]

```
Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x00000001a4c5e4f8
Termination Reason: Namespace SIGNAL, Code 5 Trace/BPT trap: 5

# Backtrace of crashed thread:
0  libswiftCore.dylib  0x00000001a4c5e4f8  _swift_runtime_on_report + 28
1  libswiftCore.dylib  0x00000001a4cc0eac  _swift_stdlib_reportFatalError + 24
2  MyApp               0x0000000100a56789  ViewController.viewDidLoad() + 120
```

**Verify**: You can identify the exception type (EXC_BREAKPOINT, EXC_BAD_ACCESS, EXC_CRASH, etc.) and the faulting frame.

### 3. Enable diagnostic tools in Xcode

Turn on runtime sanitizers and checkers for the Debug scheme. [src1, src5]

```
Xcode > Product > Scheme > Edit Scheme > Run > Diagnostics:

[x] Address Sanitizer (ASan)     — detects use-after-free, buffer overflow
[x] Thread Sanitizer (TSan)      — detects data races (cannot use with ASan)
[x] Main Thread Checker          — detects UI calls from background threads
[x] Zombie Objects               — detects messages to deallocated objects
[x] Undefined Behavior Sanitizer — detects UB in C/C++/ObjC code

Only enable ONE of ASan or TSan at a time. They are mutually exclusive.
```

**Verify**: Run the app. If ASan or TSan detects an issue, Xcode pauses at the violation with a detailed diagnostic.

### 4. Debug EXC_BAD_ACCESS with Zombie Objects

When the crash is at `objc_msgSend` with an invalid address, enable Zombie Objects to identify the deallocated object. [src5]

```
Xcode > Scheme > Run > Diagnostics > [x] Zombie Objects

# When the zombie is accessed, Xcode prints:
# *** -[MyViewController respondsToSelector:]: message sent to deallocated instance 0x600003a08000

# In lldb, inspect the zombie:
(lldb) po 0x600003a08000
# Output: <_NSZombie_MyViewController: 0x600003a08000>
```

**Verify**: The console message identifies the class of the deallocated object, showing exactly which object was accessed after deallocation.

### 5. Analyze memory issues with Instruments Allocations

For jetsam/OOM crashes, profile memory usage to find the allocation spike. [src7]

```
Xcode > Product > Profile (Cmd+I) > Allocations

# In Instruments:
1. Record the session while reproducing the high-memory scenario
2. Look at "All Heap & Anonymous VM" for total memory
3. Sort by "Persistent Bytes" to find the largest allocations
4. Check "Mark Generation" between actions to see per-action growth
5. iOS apps are jetsammed at ~1.5-2GB on modern devices (varies by device)
```

**Verify**: `Persistent Bytes` total stays under the device memory limit. Growth per generation should stabilize, not increase linearly.

### 6. Set up crash reporting for production

Configure Crashlytics, Sentry, or MetricKit to capture crashes from production users. [src4, src6]

```swift
// MetricKit (built-in, iOS 14+) — no third-party SDK needed
import MetricKit

class MetricSubscriber: NSObject, MXMetricManagerSubscriber {
    func didReceive(_ payloads: [MXDiagnosticPayload]) {
        for payload in payloads {
            if let crashDiagnostics = payload.crashDiagnostics {
                for crash in crashDiagnostics {
                    // crash.callStackTree contains symbolicated frames
                    print(crash.callStackTree.jsonRepresentation())
                }
            }
        }
    }
}

// Register in AppDelegate
let subscriber = MetricSubscriber()
MXMetricManager.shared.add(subscriber)
```

**Verify**: After a crash, `didReceive(_:)` is called within 24 hours with the diagnostic payload containing the call stack tree.

## Code Examples

### Swift: Safe optional handling patterns

```swift
// Input:  Optional values from network/DB/user input
// Output: Crash-safe code that handles nil gracefully

// PATTERN 1: guard let (early return)
func processUser(data: [String: Any]?) {
    guard let data = data,
          let name = data["name"] as? String,
          let age = data["age"] as? Int else {
        print("Invalid user data")
        return
    }
    // name and age are guaranteed non-nil here
    print("\(name), age \(age)")
}

// PATTERN 2: if let (conditional execution)
if let url = URL(string: urlString) {
    UIApplication.shared.open(url)
}

// PATTERN 3: nil coalescing (default value)
let displayName = user.name ?? "Anonymous"

// PATTERN 4: Optional chaining
let count = user.orders?.filter { $0.isPaid }?.count ?? 0
```

### Swift: Safe collection access

```swift
// Input:  Array with unknown bounds
// Output: Crash-safe subscript access

extension Collection {
    /// Returns the element at the specified index if within bounds, nil otherwise
    subscript(safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }
}

// Usage — never crashes
let items = ["a", "b", "c"]
let item = items[safe: 5]  // nil instead of crash
let first = items.first    // Optional — safe
let last = items.last      // Optional — safe
```

### Objective-C: Zombie and unrecognized selector defense

```objc
// Input:  Delegate callbacks and selector invocations
// Output: Crash-safe patterns for dynamic dispatch

// PATTERN 1: Weak delegate (prevents EXC_BAD_ACCESS)
@interface MyClass ()
@property (nonatomic, weak) id<MyDelegate> delegate;  // MUST be weak
@end

// PATTERN 2: Check selector before calling
if ([self.delegate respondsToSelector:@selector(didFinishLoading:)]) {
    [self.delegate didFinishLoading:self];
}

// PATTERN 3: Safe KVO removal with token
@implementation MyObserver {
    NSKeyValueObservation *_observation;
}
- (void)startObserving:(MyModel *)model {
    _observation = [model observe:@selector(status)
                          options:NSKeyValueObservingOptionNew
                          handler:^(MyModel *obj, NSKeyValueChange *change) {
        NSLog(@"Status changed: %@", change.newValue);
    }];
    // _observation auto-removes on dealloc — no manual removeObserver needed
}
@end
```

## Anti-Patterns

### Wrong: Force-unwrapping optionals from external data

```swift
// BAD — network response can be nil; force-unwrap crashes the app [src1, src6]
let json = try JSONSerialization.jsonObject(with: data) as! [String: Any]
let name = json["name"] as! String
let age = json["age"] as! Int
```

### Correct: Conditional unwrapping with error handling

```swift
// GOOD — graceful handling of missing or mistyped data [src1, src6]
guard let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
      let name = json["name"] as? String,
      let age = json["age"] as? Int else {
    throw DataError.invalidFormat
}
```

### Wrong: Blocking the main thread with synchronous network calls

```swift
// BAD — blocks main thread; watchdog kills app after 20s on launch [src3]
func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions opts: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    let data = try! Data(contentsOf: URL(string: "https://api.example.com/config")!)
    self.config = try! JSONDecoder().decode(Config.self, from: data)
    return true
}
```

### Correct: Async loading with default fallback

```swift
// GOOD — non-blocking; loads config async with cached fallback [src3]
func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions opts: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    self.config = Config.loadCached() ?? Config.defaults
    Task {
        if let fresh = try? await fetchConfig() {
            self.config = fresh
            fresh.saveToCache()
        }
    }
    return true
}
```

### Wrong: Strong delegate reference causing retain cycle and zombie access

```swift
// BAD — strong reference creates retain cycle; if delegate is deallocated
// while referenced, accessing it crashes with EXC_BAD_ACCESS [src5, src6]
class NetworkManager {
    var delegate: NetworkDelegate?  // STRONG reference — crash risk
}
```

### Correct: Weak delegate reference

```swift
// GOOD — weak reference breaks retain cycle; nil check prevents crash [src5, src6]
class NetworkManager {
    weak var delegate: NetworkDelegate?  // WEAK — safe

    func notifyCompletion() {
        delegate?.didComplete()  // Optional chaining — safe if deallocated
    }
}
```

### Wrong: Passing Core Data objects across threads

```swift
// BAD — NSManagedObject is not thread-safe [src1, src4]
let user = viewContext.fetch(request).first!  // Main thread context
DispatchQueue.global().async {
    print(user.name)  // EXC_BAD_ACCESS — accessing main context object on background thread
}
```

### Correct: Use objectID and fetch on the correct context

```swift
// GOOD — objectID is thread-safe; fetch on the correct context [src1, src4]
let userID = user.objectID  // Thread-safe
DispatchQueue.global().async {
    let bgContext = persistentContainer.newBackgroundContext()
    bgContext.perform {
        let bgUser = bgContext.object(with: userID) as! User
        print(bgUser.name)  // Safe — accessed on bgContext's queue
    }
}
```

## Common Pitfalls

- **Crash report not symbolicated**: Without dSYMs, you see `0x100a56789` instead of `ViewController.viewDidLoad:42`. Fix: always archive builds with dSYMs; upload dSYMs to Crashlytics/Sentry; use `xcrun atos` for manual symbolication. [src1, src4]
- **Watchdog kill misidentified as crash**: 0x8badf00d is not an exception — it is the OS killing a non-responsive app. The crash report has `Termination Reason: FRONTBOARD`, not `Exception Type`. Fix: focus on main thread blocking, not memory bugs. [src3]
- **Zombie Objects left enabled in Release**: NSZombie prevents deallocation. If accidentally shipped, app memory grows unbounded. Fix: verify scheme settings — Zombie Objects should only be checked in Debug, never Release or Profile. [src5]
- **`unowned` used where `weak` should be**: `unowned` crashes immediately if the referenced object is deallocated. `weak` safely becomes nil. Fix: use `weak` by default; only use `unowned` when you can prove the referenced object outlives the reference. [src5, src6]
- **Ignoring MetricKit diagnostic payloads**: MetricKit delivers crash and hang diagnostics within 24 hours, but many apps never register an `MXMetricManagerSubscriber`. Fix: register a subscriber in `didFinishLaunchingWithOptions`. [src1]
- **Testing only on simulator**: Many crash patterns (watchdog, jetsam, GPU memory) only manifest on real devices. Fix: always test on physical hardware before release. [src3, src7]
- **Not using `#available` for new APIs**: Calling an API unavailable on the user's iOS version causes `EXC_BAD_ACCESS` or `Symbol not found`. Fix: always guard with `if #available(iOS 17, *)`. [src1, src6]

## Diagnostic Commands

> Full script: [diagnostic-commands.sh](scripts/diagnostic-commands.sh) (36 lines)

```bash
# === Symbolicate a crash address ===
xcrun atos -arch arm64 \
  -o MyApp.app.dSYM/Contents/Resources/DWARF/MyApp \
  -l 0x100a40000 \
  0x100a56789
# ... (see full script)
```

## Version History & Compatibility

| iOS / Xcode Version | Status | Key Crash Debugging Features | Notes |
|---|---|---|---|
| iOS 18 / Xcode 16 | Current | Swift 6 strict concurrency; enhanced crash reports with actor isolation info | Swift 6 mode catches data races at compile time [src2] |
| iOS 17 / Xcode 15 | Supported | Interactive crash logs in Xcode Organizer; improved MetricKit payloads | MetricKit now includes hang diagnostics |
| iOS 16 / Xcode 14 | Supported | Swift concurrency runtime checks; async backtraces in lldb | `SWIFT_DETERMINISTIC_HASHING` for debugging |
| iOS 15 / Xcode 13 | Maintenance | MetricKit crash diagnostics (MXCrashDiagnostic); extended launch stall reporting | First version with crash diagnostics in MetricKit |
| iOS 14 / Xcode 12 | Deprecated | MetricKit basic metrics; App Clips crash separation | MetricKit v1 (metrics only, no crash diagnostics) |
| iOS 13 / Xcode 11 | EOL | SwiftUI initial release; Combine framework crashes | Many SwiftUI crashes fixed in iOS 14+ |

## When to Use / When Not to Use

| Use When | Don't Use When | Use Instead |
|---|---|---|
| Your iOS app crashes and you have a crash report | App hangs but does not crash | Instruments Time Profiler + `MXAppExitMetric` for hang analysis |
| Crash report shows Exception Type: EXC_BAD_ACCESS, EXC_CRASH, or EXC_BREAKPOINT | Crash is in a React Native / Flutter JS/Dart layer | Framework-specific debugger (Flipper, DevTools) first, then native analysis |
| Users report crashes from TestFlight or App Store | App runs out of memory silently without crash report | Xcode Instruments Allocations + Jetsam event reports [src7] |
| Debugging Objective-C zombie object / unrecognized selector | Debugging a C/C++ library linked into the iOS app | software/debugging/c-cpp-segfault/2026 — use GDB/ASan workflows |
| Need to identify the most common crash in production | Need to profile app startup time or rendering performance | Instruments Time Profiler or `os_signpost` |

## Important Caveats

- **Crash-free rate benchmarks**: Apple considers 99% crash-free (by session) as acceptable. Top apps target 99.9%+. Below 99%, Apple may flag your app in App Store Connect. [src1]
- **Simulator does not reproduce all crash types**: Watchdog terminations, jetsam kills, and GPU memory crashes only occur on physical devices. Always test on real hardware. [src3, src7]
- **Swift 6 strict concurrency changes crash behavior**: Code that previously had silent data races now crashes at runtime with `EXC_BREAKPOINT` when strict concurrency is enabled. This is intentional — the crash prevents data corruption. [src2]
- **Third-party SDK crashes appear in your reports**: Crashes in Firebase, Facebook SDK, or ad frameworks show in your Xcode Organizer. Filter by your binary name in the backtrace to distinguish your code from SDK crashes. [src4]
- **MetricKit diagnostic delivery is delayed**: Crash diagnostics via MetricKit arrive within 24 hours, not immediately. For real-time crash reporting, use Crashlytics, Sentry, or Bugsnag in addition to MetricKit. [src1]

## Related Units

- [C/C++ Segfault Debugging](/software/debugging/c-cpp-segfault/2026)
- [Xcode Instruments Profiling Guide](/software/debugging/xcode-instruments-guide/2026)
- [Swift Concurrency Data Race Crashes](/software/debugging/swift-concurrency-crashes/2026)
- [iOS Performance Hangs](/software/debugging/ios-performance-hangs/2026)
