ModelActorX 是一个 Swift 库,提供了自定义的宏 ModelActorX
和 MainModelActorX
,用于增强和扩展 SwiftData 的 ModelActor
的功能。 这些宏通过允许开发者控制初始化的生成以及在 actor 和类中声明额外的变量,提供了额外的灵活性。
不要错过关于 Swift、SwiftUI、Core Data 和 SwiftData 的最新更新和精彩文章。订阅 Fatbobman's Swift Weekly,直接在您的收件箱中接收每周的见解和有价值的内容。
ModelActor
,但增加了一个 disableGenerateInit
参数,用于控制初始化的生成。MainActor
上运行的类,非常适合主线程操作,并使用 ModelContainer
的 mainContext
。disableGenerateInit
设置为 true
时,声明额外的变量并通过自定义初始化器传递它们。使用 Swift Package Manager 将 ModelActorX 添加到您的项目中。在您的 Package.swift
文件中,添加
dependencies: [
.package(url: "https://github.com/fatbobman/ModelActorX.git", from: "0.1.0")
]
或者,在 Xcode 中
https://github.com/fatbobman/ModelActorX.git
ModelActorX
宏用于定义具有类似于 SwiftData 的 ModelActor
功能的 actor。 关键区别在于 disableGenerateInit
参数,当设置为 true
时,它会阻止自动生成初始化器。 这允许您声明额外的变量并提供自定义初始化器。
@ModelActorX
actor DataHandler {
func newItem(date: Date) throws -> PersistentIdentifier {
let item = Item(timestamp: date)
modelContext.insert(item)
try modelContext.save()
return item.persistentModelID
}
func getTimestampFromItemID(_ itemID: PersistentIdentifier) -> Date? {
return self[itemID, as: Item.self]?.timestamp
}
}
@ModelActorX(disableGenerateInit: true)
actor DataHandler1 {
let date: Date
func newItem() throws -> PersistentIdentifier {
let item = Item(timestamp: date)
modelContext.insert(item)
try modelContext.save()
return item.persistentModelID
}
func getTimestampFromItemID(_ itemID: PersistentIdentifier) -> Date? {
return self[itemID, as: Item.self]?.timestamp
}
init(container: ModelContainer, date: Date) {
self.date = date
modelContainer = container
let modelContext = ModelContext(modelContainer)
modelExecutor = DefaultSerialModelExecutor(modelContext: modelContext)
}
}
MainModelActorX
宏用于生成一个在 MainActor
上运行的类。这对于 UI 更新或任何需要在主线程上执行的操作特别有用。 生成的类使用 ModelContainer
中的 mainContext
。
@MainActor
@MainModelActorX
final class MainDataHandler {
func newItem(date: Date) throws -> PersistentIdentifier {
let item = Item(timestamp: date)
modelContext.insert(item)
try modelContext.save()
return item.persistentModelID
}
func getTimestampFromItemID(_ itemID: PersistentIdentifier) -> Date? {
return self[itemID, as: Item.self]?.timestamp
}
}
@MainActor
@MainModelActorX(disableGenerateInit: true)
final class MainDataHandler1 {
let date: Date
func newItem() throws -> PersistentIdentifier {
let item = Item(timestamp: date)
modelContext.insert(item)
try modelContext.save()
return item.persistentModelID
}
func getTimestampFromItemID(_ itemID: PersistentIdentifier) -> Date? {
return self[itemID, as: Item.self]?.timestamp
}
init(container: ModelContainer, date: Date) {
self.date = date
modelContainer = container
}
}
@ModelActorX
还提供了一个使用 @MainActor
声明的构造器。 当您使用此构造器生成 actor 时,它将直接利用 mainContext
(视图上下文),并且整个 actor 将在主线程上运行。 与 @MainModelActorX
的主要区别在于,类型仍然是一个 actor
。 这意味着基于 ModelActor 构建的现有代码不需要修改——调用仍将保留 await
。
在 iOS 18 解决与使用 @ModelActor
进行更新相关的响应性问题之前,此方法可能是一个理想的临时解决方案。
@ModelActorX
actor DataHandler {}
Task{ @MainActor in
let handler = DataHandler(mainContext: container.mainContext) // Use the view context for construction
await handler.updateItem(id: id) // Even on the main thread, you can still use `await`
}
struct ModelActorXTests {
@Test func example1() async throws {
let container = createContainer()
let handler = DataHandler(modelContainer: container)
let now = Date.now
let id = try await handler.newItem(date: now)
let date = await handler.getTimestampFromItemID(id)
#expect(date == now)
}
@Test func example2() async throws {
let container = createContainer()
let now = Date.now
let handler = DataHandler1(container: container, date: now)
let id = try await handler.newItem()
let date = await handler.getTimestampFromItemID(id)
#expect(date == now)
}
}
@MainActor
struct MainModelActorXTests {
@Test
func test1() async throws {
let container = createContainer()
let handler = MainDataHandler(modelContainer: container)
let now = Date.now
let id = try handler.newItem(date: now)
let date = handler.getTimestampFromItemID(id)
#expect(date == now)
}
@Test
func test2() async throws {
let container = createContainer()
let now = Date.now
let handler = MainDataHandler1(container: container, date: now)
let id = try handler.newItem()
let date = handler.getTimestampFromItemID(id)
#expect(date == now)
}
}
disableGenerateInit: Bool
(可选):控制是否自动生成初始化器。 默认值为 false
。disableGenerateInit: Bool
(可选):控制是否自动生成初始化器。 默认值为 false
。ModelActorX 根据 MIT 许可证发布。 有关详细信息,请参阅 LICENSE。
ModelActor
功能。欢迎贡献!如果您有改进的想法或发现错误,请打开一个 issue 或提交一个 pull request。