> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flashcat.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# iOS

> 掌握 iOS RUM SDK 的异常捕获机制，包括崩溃捕获、App Hangs、Watchdog 终止、手动上报和 dSYM 符号化

本文档介绍 iOS RUM SDK 的异常捕获机制，帮助您监控和诊断 iOS 应用中的崩溃和错误问题。

<Info>
  SDK 支持自动捕获应用崩溃、App Hangs（应用挂起）、Watchdog 终止，同时提供手动错误上报和 dSYM 符号化功能。
</Info>

## 异常类型

iOS RUM 可以监控以下类型的异常：

### 应用崩溃

SDK 自动捕获未处理的异常和致命信号，包括：

* 未捕获的 Swift/Objective-C 异常
* 致命信号（如 `SIGSEGV`、`SIGABRT`）
* Mach 异常

### App Hangs（应用挂起）

当主线程被阻塞超过指定阈值时，SDK 会检测并报告 App Hang 事件，帮助您发现影响用户体验的卡顿问题。

### Watchdog 终止

iOS 系统的 Watchdog 机制会终止长时间无响应的应用。SDK 可以检测这类终止并报告为崩溃事件。

### 自定义错误

除了自动捕获的异常外，您还可以使用 RUM SDK 手动上报自定义异常，用于跟踪业务逻辑错误等特定问题。

## 配置崩溃报告

### 添加 Crash Reporting 模块

要启用崩溃报告功能，需要添加 `FlashcatCrashReporting` 模块。

#### Swift Package Manager

在 Xcode 中添加包依赖时，同时添加以下模块：

* `FlashcatCore`：核心 SDK
* `FlashcatRUM`：RUM 功能模块
* `FlashcatCrashReporting`：崩溃报告模块

### 初始化崩溃报告

在 SDK 初始化后启用崩溃报告：

```swift AppDelegate.swift theme={null}
import FlashcatCore
import FlashcatRUM
import FlashcatCrashReporting

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        // 初始化 Flashcat SDK
        Flashcat.initialize(
            with: Flashcat.Configuration(
                clientToken: "<CLIENT_TOKEN>",
                env: "<ENV_NAME>"
            ),
            trackingConsent: .granted
        )

        // 启用崩溃报告
        CrashReporting.enable()

        // 启用 RUM
        RUM.enable(
            with: RUM.Configuration(
                applicationID: "<RUM_APPLICATION_ID>"
            )
        )

        return true
    }
}
```

<Tip>
  建议在 `application(_:didFinishLaunchingWithOptions:)` 中尽早初始化 SDK 和崩溃报告，以确保能捕获应用启动阶段的崩溃。
</Tip>

## 配置 App Hangs 检测

App Hang 是指主线程被阻塞导致应用无法响应用户输入的情况。SDK 可以检测这类问题并上报。

### 启用 App Hangs 追踪

在 RUM 配置中设置 `appHangThreshold` 参数：

```swift theme={null}
import FlashcatRUM

RUM.enable(
    with: RUM.Configuration(
        applicationID: "<RUM_APPLICATION_ID>",
        appHangThreshold: 0.25  // 250 毫秒
    )
)
```

### App Hang 阈值说明

| 阈值设置   | 描述             | 适用场景        |
| ------ | -------------- | ----------- |
| `0.25` | 250 毫秒，检测轻微卡顿  | 对流畅度要求极高的应用 |
| `1.0`  | 1 秒，检测明显卡顿     | 一般应用推荐值     |
| `nil`  | 禁用 App Hang 检测 | 默认设置        |

<Tip>
  **配置建议：**

  * 设置过低的阈值可能会产生大量报告，建议根据应用实际情况调整
  * 如果 App Hang 导致应用被 Watchdog 终止，该事件会被标记为崩溃类型
</Tip>

## 配置 Watchdog 终止追踪

iOS 的 Watchdog 机制会终止长时间无响应的应用。SDK 可以在下次应用启动时检测并报告这类终止。

### 启用 Watchdog 终止追踪

```swift theme={null}
import FlashcatRUM

RUM.enable(
    with: RUM.Configuration(
        applicationID: "<RUM_APPLICATION_ID>",
        trackWatchdogTerminations: true
    )
)
```

### Watchdog 终止检测条件

SDK 会在以下条件全部满足时将上次应用终止判定为 Watchdog 终止：

* 应用不是被用户强制退出
* 上次运行未发生崩溃或 fatal error
* 应用未进行升级
* 应用在前台且正在响应事件

## 手动错误上报

通过 `addError` API，您可以手动上报已处理的异常、自定义错误或其他未被自动捕获的错误。

### 上报错误示例

```swift theme={null}
import FlashcatRUM

// 上报带有上下文的错误
RUMMonitor.shared().addError(
    message: "网络请求失败",
    type: "NetworkError",
    source: .network,
    attributes: [
        "url": "https://api.example.com",
        "status_code": 500,
        "userId": "12345"
    ]
)
```

### 错误来源类型

| 来源         | 描述         |
| ---------- | ---------- |
| `.source`  | 源码错误       |
| `.network` | 网络错误       |
| `.webview` | WebView 错误 |
| `.console` | 控制台错误      |
| `.custom`  | 自定义错误      |

### 上报异常对象示例

```swift theme={null}
import FlashcatRUM

do {
    try riskyOperation()
} catch {
    RUMMonitor.shared().addError(
        error: error,
        source: .source,
        attributes: [
            "operation": "riskyOperation",
            "timestamp": Date().timeIntervalSince1970
        ]
    )
}
```

## 获取符号化的堆栈跟踪

崩溃报告中的堆栈默认为内存地址。通过上传 dSYM 符号文件，可以将这些地址转换为可读的函数名、文件名和行号。

### 什么是 dSYM 文件

dSYM（Debug Symbol）文件包含了应用的调试符号信息，用于将崩溃堆栈中的内存地址映射到源代码位置。

### 使用命令行工具上传 dSYM

<Steps>
  <Step title="安装 flashcat-ci 工具">
    ```bash theme={null}
    npm install -g @flashcat/flashcat-ci
    ```
  </Step>

  <Step title="上传 dSYM 文件">
    ```bash theme={null}
    export FLASHCAT_API_KEY="<API_KEY>"

    flashcat-ci dsyms upload /path/to/dSYMs
    ```

    <Check>
      **支持的文件格式：**

      * `.dSYM` 目录
      * `.dSYM.zip` 压缩包
      * 包含多个 dSYM 的 `.zip` 压缩包
    </Check>
  </Step>
</Steps>

### 在 CI/CD 中集成 dSYM 上传

#### Xcode Build Phase 脚本

在 Xcode 项目的 Build Phases 中添加 Run Script：

```bash theme={null}
#!/bin/bash

if [ "$CONFIGURATION" = "Release" ]; then
    export FLASHCAT_API_KEY="<API_KEY>"
    flashcat-ci dsyms upload "${DWARF_DSYM_FOLDER_PATH}"
fi
```

#### Fastlane 集成

在 `Fastfile` 中添加上传步骤：

```ruby theme={null}
lane :upload_dsyms do
  ENV["FLASHCAT_API_KEY"] = "<API_KEY>"

  sh("flashcat-ci dsyms upload #{lane_context[SharedValues::DSYM_OUTPUT_PATH]}")
end
```

### Bitcode 应用的 dSYM

如果您的应用启用了 Bitcode，Apple 会在 App Store 处理时重新编译应用，生成新的 dSYM 文件。您需要从 App Store Connect 下载这些 dSYM 并上传。

#### 下载 Bitcode dSYM

<Steps>
  <Step title="登录 App Store Connect">
    访问 [App Store Connect](https://appstoreconnect.apple.com) 并登录您的账号。
  </Step>

  <Step title="选择构建版本">
    进入您的应用 → 活动 → 选择需要下载 dSYM 的构建版本。
  </Step>

  <Step title="下载 dSYM">
    点击「下载 dSYM」按钮，下载完成后使用 flashcat-ci 工具上传。
  </Step>
</Steps>

### dSYM 文件限制

* 每个 dSYM 文件大小限制为 **2 GB**
* 仅真实设备上的崩溃支持符号化，模拟器生成的崩溃不支持

## 追踪后台事件

默认情况下，只有在视图处于活动状态时发生的崩溃才会被追踪。如果您希望追踪应用在后台时发生的崩溃，可以启用后台事件追踪：

```swift theme={null}
import FlashcatRUM

RUM.enable(
    with: RUM.Configuration(
        applicationID: "<RUM_APPLICATION_ID>",
        trackBackgroundEvents: true
    )
)
```

<Warning>
  追踪后台事件可能会产生额外的会话，这可能会影响计费。如有疑问，请联系 Flashcat 支持团队。
</Warning>

## 限制与注意事项

### 崩溃检测限制

* **SDK 初始化时机**：崩溃只有在 SDK 和 `CrashReporting.enable()` 调用之后才能被检测到。建议尽早初始化。
* **调试器干扰**：在 Xcode 调试器连接时，崩溃会被调试器捕获而非 SDK。测试崩溃报告时，请在不连接调试器的情况下运行应用。
* **崩溃报告上传时机**：崩溃报告会在应用下次启动时上传，因此崩溃发生后需要重新启动应用才能看到报告。

### 符号化限制

* 仅真实设备上的崩溃支持符号化，模拟器生成的崩溃不支持。
* 每个发布版本都需要上传对应的 dSYM 文件。
* 如果使用 Bitcode，需要从 App Store Connect 下载并上传重新生成的 dSYM。

### App Hang 检测限制

* App Hang 检测仅在应用处于前台时有效。
* 检测精度取决于阈值设置，过低的阈值可能产生大量误报。

## 测试验证

### 验证崩溃报告

1. **不连接调试器运行应用**：从 Xcode 停止应用，然后从设备上直接启动。

2. **触发测试崩溃**：

```swift theme={null}
func triggerTestCrash() {
    fatalError("测试崩溃")
}
```

3. **重启应用**：崩溃发生后，从设备上重新启动应用，等待 SDK 上传崩溃报告。

4. **查看报告**：在 Flashcat 控制台的异常追踪模块中查看崩溃报告。

### 验证 App Hang

1. 在主线程执行耗时操作：

```swift theme={null}
func blockMainThread() {
    Thread.sleep(forTimeInterval: 5)  // 阻塞主线程 5 秒
}
```

2. 触发该操作后尝试与应用交互。

3. 检查 Flashcat 控制台是否收到 App Hang 报告。

### 验证符号化

1. 确保已上传对应版本的 dSYM 文件。
2. 触发崩溃并查看报告。
3. 确认堆栈中显示的是函数名、文件名和行号，而非纯内存地址。

## 错误数据结构

每条错误数据包含以下属性：

| 属性               | 类型      | 描述                                       |
| ---------------- | ------- | ---------------------------------------- |
| `error.source`   | string  | 错误来源（如 `source`、`network`、`custom`）      |
| `error.type`     | string  | 错误类型（如 `NSException`、`Signal`）           |
| `error.message`  | string  | 错误消息                                     |
| `error.stack`    | string  | 错误堆栈跟踪                                   |
| `error.is_crash` | boolean | 是否为崩溃                                    |
| `context`        | Object  | 自定义上下文信息，通过 `addError` 的 `attributes` 传入 |

## 最佳实践

1. **尽早初始化 SDK**：在 `application(_:didFinishLaunchingWithOptions:)` 中尽早调用 `Flashcat.initialize()` 和 `CrashReporting.enable()`。

2. **正确上传 dSYM**：

   * 为每个发布版本上传对应的 dSYM 文件
   * 在 CI/CD 流程中集成 dSYM 上传
   * 如果使用 Bitcode，及时从 App Store Connect 下载并上传 dSYM

3. **合理设置 App Hang 阈值**：根据应用性能要求设置合适的阈值，避免过多误报。

4. **丰富错误上下文**：在手动上报错误时，附加业务相关的上下文信息（如用户 ID、操作类型）。

5. **测试时断开调试器**：验证崩溃报告功能时，确保不连接 Xcode 调试器。

## 下一步

<CardGroup cols={2}>
  <Card title="查看异常" icon="eye" href="/zh/rum/error-tracking/error-viewing">
    了解如何在异常追踪模块查看和分析 Issue
  </Card>

  <Card title="高级配置" icon="sliders" href="/zh/rum/sdk/ios/advanced-config">
    配置 iOS SDK 的高级功能
  </Card>
</CardGroup>
