做企業(yè)網(wǎng)站收費百度競價推廣效果怎么樣
文章目錄
- 前言
- Core Data 私有隊列上下文
- SwiftData 并發(fā)支持
- 使用 ModelActor
- 合并上下文更改的問題
- 通過標識符訪問模型
- 總結(jié)
前言
SwiftData 是一個用于處理數(shù)據(jù)操作的框架,特別是在 Swift 語言中進行并發(fā)操作。本文介紹了如何在后臺執(zhí)行 SwiftData 操作以及與 Core Data 進行比較。
在 Core Data 中,可以使用私有后臺隊列上下文來執(zhí)行長時間運行的任務,以避免阻塞主隊列。SwiftData 利用了 Swift 的并發(fā)特性,通過在 ModelActor 上創(chuàng)建上下文,實現(xiàn)了類似的后臺操作。然而,與 Core Data 不同的是,SwiftData 通過編譯器強制執(zhí)行一些規(guī)則,如不允許在非主 actor 上訪問主 view 上下文。
Core Data 私有隊列上下文
在使用 Core Data 時,使用主隊列上的視圖上下文執(zhí)行 UI 操作。為了避免阻塞主隊列,可以使用私有后臺隊列上下文執(zhí)行長時間運行的任務,如解析和導入數(shù)據(jù)。
必須注意不要在隊列之間傳遞 Core Data 管理的對象。如果需要在線程之間傳遞對象,可以使用 NSManagedObjectID
來實現(xiàn)。
SwiftData 并發(fā)支持
SwiftData 利用了 Swift 的現(xiàn)代并發(fā)特性??梢允褂迷?ModelActor 上創(chuàng)建的上下文來執(zhí)行后臺工作。
與 Core Data 類似,Model 對象和 ModelContext 都不能在 actor 之間傳遞(它們都不是可發(fā)送的)。與 Core Data 不同的是,Swift 編譯器強制執(zhí)行這些規(guī)則。例如,在不在主 actor 上時嘗試訪問主視圖上下文將導致錯誤:
無法在非隔離 actor 實例上引用主 actor 隔離屬性 mainContext
使用 ModelActor
一開始,我們需要創(chuàng)建一個自己實現(xiàn)了 ModelActor
協(xié)議的 actor。模型 actor 為我們提供了要使用的上下文。ModelExecutor
控制對模型 actor 的訪問。
創(chuàng)建 actor 時,可以使用 ModelContainer
創(chuàng)建一個新的上下文,并使用它來創(chuàng)建 DefaultModelExecutor
。我的示例代碼有一個用于 Country 對象的模型,因此我可以像這樣創(chuàng)建一個模型 actor 來執(zhí)行后臺操作:
import SwiftDataactor CountryModelActor: ModelActor {let executor: any ModelExecutorinit(container: ModelContainer) {let context = ModelContext(container)executor = DefaultModelExecutor(context: context)}func doSomething() { ... }
}
注意:
- ModelContainer 是可發(fā)送的,因此我們可以安全地將其傳遞給 actor 的初始化器。
- ModelActor 有 container 和 context 屬性,但不需要直接設(shè)置它們。
我們在這個 actor 中做的任何工作都可以訪問上下文以插入、獲取和刪除所需的對象。例如,我已經(jīng)在 actor 中添加了一個方法,該方法獲取所有已訪問的國家并將 visited 標志重置為 false:
func resetVisited() throws {let fetchDescriptor: FetchDescriptor<Country> =FetchDescriptor(predicate: #Predicate { $0.visited == true }) let countries = try context.fetch(fetchDescriptor)for country in countries {country.visited = false}// 詳見下面的注釋// try context.save()
}
可能會這樣在我的視圖代碼中使用它:
func resetVisited() {Task {let actor = CountryModelActor(container: container)do {try await actor.resetVisited()} catch {logger.error("resetVisited: \(error.localizedDescription)")}}
}
合并上下文更改的問題
看到許多開發(fā)者抱怨在后臺上下文上執(zhí)行的更改不會立即合并到視圖上下文中。在當前的測試版中,如果在 actor 中保存上下文(FB12965835),也會遇到相同的問題。
如果不在 actor 中保存上下文(啟用了自動保存),則用戶界面會立即更新。這是一系列 SwiftData 中的問題之一,希望在測試版結(jié)束之前能夠得到修復。
通過標識符訪問模型
與 Core Data 一樣,如果需要在 actor 之間傳遞模型對象,應使用模型對象的持久標識符:
country.persistentModelID
ModelActor 提供了一個方便的下標,以通過標識符檢索模型對象。例如,actor 中的此方法設(shè)置了通過標識符傳遞的一組國家的 visited 標志:
func visit(identifiers: [Country.ID]) {for identifier in identifiers {if let country = self[identifier, as: Country.self] {country.visited = true}}
}
使用下標等效于編寫:
if let country = context.model(for: identifier) as? Country { ... }
總結(jié)
在操作數(shù)據(jù)模型時,需要注意不要在不同的 actors 之間傳遞管理的對象。取而代之的是,可以使用 NSManagedObjectID 來在不同的線程之間傳遞對象。
此外,文章還提到了一些問題,如在后臺上下文上執(zhí)行的更改可能不會立即合并到主視圖上下文中。然而,SwiftData 框架的優(yōu)勢在于利用了 Swift 的現(xiàn)代并發(fā)特性,為數(shù)據(jù)操作提供了更強大的支持,使開發(fā)人員能夠在處理數(shù)據(jù)時更加靈活和高效。