使用 SwiftData 风格的并发操作,革新 Core Data
欢迎使用 CoreDataEvolution,该库旨在通过结合 SwiftData 风格的优雅性和安全性,实现 Core Data 的现代化。 这个库旨在简化和增强 Core Data 对多线程的处理,从 SwiftData 的 @ModelActor
功能中汲取灵感,从而实现高效、安全和可扩展的操作。
不要错过关于 Swift、SwiftUI、Core Data 和 SwiftData 的最新更新和精彩文章。订阅Fatbobman's Swift Weekly,每周直接在您的收件箱中收到有价值的见解和内容。
SwiftData 引入了诸如 @ModelActor
之类的现代并发功能,使得处理并发数据访问变得更加容易,并且通过编译器保证了安全性。然而,SwiftData 的平台要求和在某些领域的成熟度有限,阻止了许多开发者采用它。CoreDataEvolution 弥合了这一差距,将 SwiftData 的高级设计引入 Core Data 世界,供仍然依赖 Core Data 的开发者使用。
Core Data Actor 的自定义执行器
通过使用 Swift 5.9 新的 SerialExecutor
和 ExecutorJob
协议,CoreDataEvolution 提供了自定义执行器,确保对托管对象的所有操作都在与其托管对象上下文关联的相应线程上执行。
@NSModelActor 宏@NSModelActor
宏简化了 Core Data 并发,镜像了 SwiftData 的 @ModelActor
宏。它生成必要的样板代码以在 actor 中管理 Core Data 堆栈,从而确保对托管对象的安全高效的访问。
NSMainModelActor 宏 NSMainModelActor
将提供与 NSModelActor
相同的功能,但它将用于声明在主线程上运行的类。
优雅的基于 Actor 的并发
CoreDataEvolution 允许您创建具有绑定到 Core Data 上下文的自定义执行器的 actor,从而确保 actor 中的所有操作都在上下文的线程上串行执行。
以下是如何使用 CoreDataEvolution 通过 actor 管理并发 Core Data 操作
import CoreDataEvolution
@NSModelActor
actor DataHandler {
func updateItem(identifier: NSManagedObjectID, timestamp: Date) throws {
guard let item = self[identifier, as: Item.self] else {
throw MyError.objectNotExist
}
item.timestamp = timestamp
try modelContext.save()
}
}
在此示例中,@NSModelActor
宏简化了设置,自动在 actor 内部创建所需的执行器和 Core Data 堆栈。然后,开发人员可以专注于他们的业务逻辑,而不必担心并发陷阱。
这种方法允许您安全地将现代 Swift 并发机制集成到现有的 Core Data 堆栈中,从而提高性能和代码清晰度。
您可以通过使用 disableGenerateInit
来禁用构造函数的自动生成
@NSModelActor(disableGenerateInit: true)
public actor DataHandler {
let viewName: String
func createNemItem(_ timestamp: Date = .now, showThread: Bool = false) throws -> NSManagedObjectID {
let item = Item(context: modelContext)
item.timestamp = timestamp
try modelContext.save()
return item.objectID
}
init(container: NSPersistentContainer, viewName: String) {
modelContainer = container
self.viewName = viewName
let context = container.newBackgroundContext()
context.name = viewName
modelExecutor = .init(context: context)
}
}
NSMainModelActor 将提供与 NSModelActor 相同的功能,但它将用于声明在主线程上运行的类
@MainActor
@NSMainModelActor
final class DataHandler {
func updateItem(identifier: NSManagedObjectID, timestamp: Date) throws {
guard let item = self[identifier, as: Item.self] else {
throw MyError.objectNotExist
}
item.timestamp = timestamp
try modelContext.save()
}
}
您可以使用 Swift Package Manager 将 CoreDataEvolution 添加到您的项目中,方法是将以下依赖项添加到您的 Package.swift
文件中
dependencies: [
.package(url: "https://github.com/fatbobman/CoreDataEvolution.git", .upToNextMajor(from: "0.3.0"))
]
然后,将模块导入到您的 Swift 文件中
import CoreDataEvolution
注意:由于系统限制,自定义执行器和 SerialExecutor
仅在 iOS 17/macOS 14 及更高版本上可用。
我们欢迎贡献!无论您想报告问题、提出新功能还是为代码做出贡献,都可以在 GitHub 存储库上随意打开问题或拉取请求。
CoreDataEvolution 在 MIT 许可证下可用。 有关更多信息,请参见 LICENSE 文件。
特别感谢 Swift 社区的持续支持和贡献。