我正在尝试在我的应用程序中维护服务器数据的本地副本,并认为我可以使用 swift-data 来完成此任务(事实上,我已经在官方 Apple 文档中关注了这篇关于它的文章)。但是,SwiftData 会忽略在
@Model
初始值设定项中设置的值以及任何后续更新值的尝试。
我的印象是:通过在
@Attribute(.unique)
参数上使用 id
值,每当我创建一个具有与现有模型相同 ID 的模型时,SwiftData 都会更新现有模型。看来事实并非如此。
我无法完全确定为什么 SwiftData 不允许我更新我的模型(特别是从模型自己的初始化程序内部)。这是一个错误吗?一些未记录的行为?或者我只是配置错误,或者以不受支持的方式使用这些模型?
@Model
final class Item {
@Attribute(.unique)
var id: String
var timestamp: Date
var deleted: Bool
// Initializes a local SwiftData model from a "RemoteItem", which is just a Codable
// object generated from a server response.
//
init?(from remoteModel: RemoteItem) {
guard let remoteId = remoteModel.id else { return nil }
self.id = remoteId
self.timestamp = remoteModel.timestamp
print("Initialized Item model with deletion value from remote model: \(remoteModel.deleted)")
// Prints correct value of deleted to the console (e.g. true)
self.deleted = remoteModel.deleted
print("Initialized Item model with remote deletion. Value is now: \(self.deleted)")
// Prints INCORRECT value of deleted to the console (e.g. false)
}
}
然后,在数据源参与者(或其他类似的类)中:
func fetchItems() async throws -> [Item] {
let someRemoteItems = try await networkRequestForRemoteItems()
// Map the remote items to locally cached items, similar to the demo
// provided by Apple here: https://developer.apple.com/documentation/swiftdata/maintaining-a-local-copy-of-server-data
let localItemCopies: [Item] = someRemoteItems.compactMap({ Item(from: $0) })
// "Cache" the remote items
for localItem in localItemCopies {
await cacheContainer.insert(localItem)
}
return localItemCopies
}
如上所述,SwiftData 模型存储中本地已存在的任何项目在此处再次插入时都不会更新。对于其他上下文,我看到其他问题询问类似的行为 但仅在 SwiftUI 的上下文中,这与此处无关。
PersistentModel
协议(所有
@Model
类都遵循)扩展了
Identifiable
,这意味着它带有一个
id
属性,并且该属性的类型是
PersistentIdentifier
。通过创建自己的 id 属性,您可以覆盖默认行为,我很确定这就是您的代码无法工作的原因,我不知道这是否是 SwiftData 中的错误或未正确记录的内容,但我个人从来没有将
id
属性添加到我的
@Model
类中。因此,解决我的崩溃问题以及我建议的是将 id 属性重命名为其他名称,以免干扰 SwiftData 对象的内部识别。
@Model
final class Item {
@Attribute(.unique)
var remoteId: String
//...
}
如上所述,这解决了我的崩溃问题,我可以看到现有对象正在更新,而不是新对象插入到我的列表视图中。