成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

實戰指南 | Swift 并發中的任務取消機制

開發 前端
這篇文章會講清楚任務取消的原理、如何正確使用它,以及如何寫出高效又優雅的代碼。?

前言 

Swift 并發提供了一種協作式取消(cooperative cancellation) 機制,來讓任務在需要時自己退出。簡單來說,Swift 不會強行終止你的任務,但它會告訴你任務已經被標記為取消,至于你要不要停下來,那是你自己的決定。

這篇文章會講清楚任務取消的原理、如何正確使用它,以及如何寫出高效又優雅的代碼。

什么是協作式取消? 

協作式取消的核心思想是:

  • 調用方(比如 SwiftUI)沒法直接終止任務,只能“標記”為取消。
  • 任務本身需要定期檢查這個標記,并決定要不要提前終止。
  • 你可以選擇直接返回、提供部分結果,或者繼續執行,全看你的業務邏輯。

簡單來說,Swift 只是給你一個“信號”——“嘿,這個任務已經沒用了,看看你要不要停下來”。

如何用 Task API 處理任務取消 

來看個例子,這是一個 SwiftUI 界面,用戶輸入搜索內容時,會觸發異步搜索。

struct ContentView: View {
    @Stateprivatevar store = Store()
    @Stateprivatevar query = ""
    
    var body: some View {
        NavigationStack {
            List(store.results, id: \.self) { result in
                Text(verbatim: result)
            }
            .searchable(text: $query)
            .task(id: query) {
                await store.search(matching: query)
            }
        }
    }
}

這里最關鍵的是 task(id: query) 這行代碼:

  • 當 query 變化時,SwiftUI 會啟動一個新的搜索任務。
  • 同時,它會標記上一個任務為“已取消”,但不會立刻終止它。
  • 如果舊任務里沒有檢查取消狀態,它可能仍然會跑完所有邏輯。

這意味著,如果用戶輸入了很多字符,可能會同時存在多個搜索任務,這就是為什么我們要手動處理取消邏輯。

在異步方法中正確處理取消 

假設 Store 負責查詢數據,我們的 search(matching:) 方法如下:

import HealthKit

@MainActor @Observablefinalclass Store {
    private(set) var results: [HKCorrelation] = []
    privatelet store = HKHealthStore()
    
    func search(matching query: String) async {
        let foodQuery = HKSampleQueryDescriptor(
            predicates: [.correlation(type: .init(.food))],
            sortDescriptors: []
        )
        
        do {
            let food = try await foodQuery.result(for: store)
            
            tryTask.checkCancellation()  // 檢查任務是否已取消
            
            results = food.filter { food in
                let title = food.metadata?["title"] as? String ?? ""
                return title.localizedStandardContains(query)
            }
        } catch {
            results = []
        }
    }
}

這里有個關鍵點:**Task.checkCancellation()**。

  • 這個方法會拋出一個錯誤,如果任務已經被取消,它就會立刻停止執行,后續的代碼不會再運行。
  • 這樣可以避免執行一些不必要的邏輯,比如過濾數據、更新 UI 等。
  • 如果任務被取消,我們直接把 results 置空,這樣用戶不會看到過時的搜索結果。

在多個步驟中檢查取消狀態 

如果你的異步代碼有多個步驟,比如先獲取數據、然后再做一些處理,那你可能需要在多個關鍵點檢查任務是否已取消,否則即使任務已經無效了,它可能還會跑完整個流程。

import HealthKit

@MainActor @Observablefinalclass Store {
    private(set) var results: [HKCorrelation] = []
    privatelet store = HKHealthStore()
    
    func search(matching query: String) async {
        let foodQuery = HKSampleQueryDescriptor(
            predicates: [.correlation(type: .init(.food))],
            sortDescriptors: []
        )
        
        do {
            let food = try await foodQuery.result(for: store)
            
            tryTask.checkCancellation()  // 第一次取消檢查
            
            // 假設這里有額外的數據處理
            tryTask.checkCancellation()  // 第二次取消檢查
            
            results = food.filter { food in
                let title = food.metadata?["title"] as? String ?? ""
                return title.localizedStandardContains(query)
            }
        } catch {
            results = []
        }
    }
}

為什么要多次檢查?

  • 如果 foodQuery 運行了一段時間,任務被取消了,我們希望盡早停下來,而不是等所有代碼都跑完。
  • 某些任務可能是分步執行的,比如先獲取原始數據,再處理數據。如果第一步完成了,但任務已經取消了,我們就沒必要繼續處理數據。

用 isCancelled 進行檢查 

除了 Task.checkCancellation() 之外,Swift 還提供了 Task.isCancelled 這個屬性,它是一個布爾值,你可以用它更靈活地處理任務取消:

actor SearchService {
    privatevar cachedResults: [HKCorrelation] = []
    privatelet store = HKHealthStore()
    
    func search(matching query: String) async throws -> [HKCorrelation] {
        guard !Task.isCancelled else {
            return cachedResults  // 任務取消了,直接返回緩存
        }
        
        let foodQuery = HKSampleQueryDescriptor(
            predicates: [.correlation(type: .init(.food))],
            sortDescriptors: []
        )
        
        let food = try await foodQuery.result(for: store)
        
        guard !Task.isCancelled else {
            return cachedResults  // 任務取消了,避免不必要的計算
        }
        
        cachedResults = food.filter { food in
            let title = food.metadata?["title"] as? String ?? ""
            return title.localizedStandardContains(query)
        }
        
        return cachedResults
    }
}

兩種方式的區別:

  • Task.checkCancellation():如果任務已取消,直接拋出錯誤,代碼不再繼續執行。
  • Task.isCancelled:任務是否繼續執行,由你自己決定,比如可以提前返回緩存數據,而不是直接終止。

手動取消任務 

通常情況下,Swift 會幫你管理任務的取消,但如果你想手動創建和取消任務,也可以用 Task:

struct ExampleView: View {
    @Stateprivatevar store = Store()
    @Stateprivatevar task: Task<Void, Never>?
    
    var body: some View {
        VStack {
            Button("開始任務") {
                task = Task {
                    await store.fetch()
                }
            }
            
            Button("取消任務") {
                task?.cancel()
            }
        }
    }
}

這里 task?.cancel() 只會標記任務為取消,但不會真的終止它,所以你仍然需要在 fetch() 里檢查 Task.isCancelled 或 Task.checkCancellation()。

總結 

  • Swift 不會自動終止任務,只會標記它為取消。
  • 用 Task.checkCancellation() 可以立即終止任務,防止執行不必要的邏輯。
  • 用 Task.isCancelled 可以更靈活地決定如何處理取消。
  • 如果任務有多個異步步驟,應該在關鍵點多次檢查取消狀態。
  • 手動創建的任務可以用 .cancel() 取消,但仍然需要手動檢查取消狀態。

學會這些,你的 Swift 并發代碼就能更高效、更優雅地處理任務取消,讓用戶體驗更流暢!

責任編輯:姜華 來源: Swift社區
相關推薦

2014-07-29 11:20:28

Swift豆瓣電臺編程實戰

2022-04-26 08:41:38

Swift并發系統iOS

2025-03-19 09:02:18

Debouncing任務讓步Swift

2024-04-09 08:04:42

C#結構await

2025-04-07 01:02:00

GoAPI語言

2023-04-26 11:59:06

Swift異步編程

2024-05-11 08:31:20

中斷機制插隊機制React

2018-03-15 16:45:47

前端JavaScriptthis

2021-02-02 14:55:48

React前端高優先

2023-11-06 14:13:51

asyncio開發

2024-08-09 10:59:01

KubernetesSidecar模式

2011-12-12 11:16:02

iOS并發編程

2025-03-26 00:55:00

2021-07-22 09:43:09

Golang語言并發機制

2017-01-13 22:42:15

iosswift

2020-11-20 07:51:02

JavaSPI機制

2009-06-02 10:32:30

Oracle并發處理

2016-10-09 14:41:40

Swift開發ARC

2013-12-12 16:44:25

Lua協程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 免费天天干 | 日本a级大片 | 日韩在线电影 | 黄色欧美大片 | 亚洲精品福利在线 | 一区二区三区四区av | www.激情.com| 91精品久久久久久久久中文字幕 | 操久久| 亚洲国产黄色av | 日韩精品亚洲专区在线观看 | 在线观看免费毛片 | 最新日韩在线 | 亚洲人成网亚洲欧洲无码 | 国产一区二区在线视频 | 欧美黄色片在线观看 | 麻豆精品久久久 | 成人在线免费观看视频 | 国产真实精品久久二三区 | 精品中文在线 | 国产精品极品美女在线观看免费 | 九九久久精品视频 | 99精品在线| 欧美日韩在线高清 | 精品国产一区二区三区观看不卡 | 亚洲午夜精品视频 | 国产成人精品综合 | 黄色毛片免费看 | 精品福利在线 | 午夜精品网站 | www.久久 | 97热在线| 日韩视频在线播放 | 国产成人av一区二区三区 | 亚洲成av人片在线观看 | 亚洲一区二区三区在线 | 超碰综合| 日韩视频 中文字幕 | 免费久久网 | 99久久精品国产毛片 | 黄色毛片在线观看 |