claude-code/claude-zh/skills/swift-concurrency-6-2/SKILL.md

69 lines
3.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: swift-concurrency-6-2
description: Swift 6.2 易用併發模式 — 預設單線程、顯式標註 @concurrent 以進行背景負載平衡,以及針對 MainActor 類型的隔離型協定Isolated Conformances
---
# Swift 6.2 易用併發模式 (Approachable Concurrency)
這是採用 Swift 6.2 併發模型的實踐模式。在該模型中,程式碼預設在單線程運行,僅在顯式標註時才引入併發。這能消除常見的資料競爭 (Data-race) 錯誤,同時不犧牲效能。
## 何時啟用
- 將 Swift 5.x 或 6.0/6.1 專案遷移至 Swift 6.2。
- 解決編譯器回報的資料競爭安全錯誤。
- 設計基於 `@MainActor` 的應用程式架構。
- 需要將消耗大量 CPU 的工作移至背景線程處理。
- 在 MainActor 隔離類型上實作協定順應性 (Protocol Conformances)。
## 核心概念:預設單線程行為
在 Swift 6.1 之前的版本中,`async` 函式可能會被隱含地移至背景線程,導致即使是看似安全的程式碼也會觸發資料競爭。
**Swift 6.2 修正了這一點**:非同步函式預設會保留在「調用者」所在的 Actor 上(通常是 MainActor
### 核心模式 1 — 隔離型協定 (Isolated Conformances)
MainActor 類型現在可以安全地順應非隔離的協定:
```swift
protocol Exportable {
func export()
}
// Swift 6.2:使用隔離性順應性,編譯器保證該協定內容僅在 MainActor 上執行
extension StickerModel: @MainActor Exportable {
func export() {
photoProcessor.exportAsPNG()
}
}
```
### 核心模式 2 — 顯式背景處理 `@concurrent`
當你真正需要平行處理效能時,顯式使用 `@concurrent` 標記將任務移交給併發線程池:
```swift
nonisolated final class PhotoProcessor {
// 顯式將耗時作業移至背景
@concurrent
static func extractSubject(from data: Data) async -> Sticker { /* 處理邏輯 ... */ }
}
// 調用者必須使用 await
let sticker = await PhotoProcessor.extractSubject(from: data)
```
## 遷移建議
1. **Xcode 設定**:在 Build Settings 的 Swift Compiler -> Concurrency 區段啟用相關功能。
2. **預設使用 MainActor**:建議應用程式 Target 啟用「預設推斷 MainActor」模式減少手動標記範本代碼。
3. **優化熱點路徑**:先進行測速效能分析 (Profile),僅針對真正的效能瓶頸(如圖片處理、大型計算)才掛上 `@concurrent`
## 實踐之最佳實踐
- **從 MainActor 開始**:優先撰寫單線程程式碼,優化留到最後。
- **僅針對運算密集型工作使用 `@concurrent`**:如編碼、壓縮、複雜算法。
- **相信編譯器**:如果編譯器報告資料競爭,則代表程式碼邏輯確實存在併發風險,請勿試圖使用 `nonisolated` 掩蓋問題。
## 應避免的反模式
- 對每一個 `async` 函式都標記 `@concurrent`(大多數情況下並不需要背景執行)。
- 假設所有非同步程式碼都在背景執行(在 Swift 6.2 中,預設是留在原 Actor 執行的)。