SwiftData 模型未更新 init 中提供的值

问题描述 投票:0回答:1

我正在尝试在我的应用程序中维护服务器数据的本地副本,并认为我可以使用 来完成此任务(事实上,我已经在官方 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 的上下文中,这与此处无关。

ios swift caching swift-data
1个回答
0
投票
我无法完全复制您的问题,但我确实让我的代码崩溃了,所以我将发布针对该崩溃的解决方案,因为我相信这是相同的根本问题。

PersistentModel

协议(所有
@Model
类都遵循)扩展了
Identifiable
,这意味着它带有一个
id
属性,并且该属性的类型是
PersistentIdentifier

通过创建自己的 id 属性,您可以覆盖默认行为,我很确定这就是您的代码无法工作的原因,我不知道这是否是 SwiftData 中的错误或未正确记录的内容,但我个人从来没有将

id

 属性添加到我的 
@Model
 类中。

因此,解决我的崩溃问题以及我建议的是将 id 属性重命名为其他名称,以免干扰 SwiftData 对象的内部识别。

@Model final class Item { @Attribute(.unique) var remoteId: String //... }
如上所述,这解决了我的崩溃问题,我可以看到现有对象正在更新,而不是新对象插入到我的列表视图中。

© www.soinside.com 2019 - 2024. All rights reserved.