SwiftData中@Query使用计算属性作过滤条件崩溃问题咨询
SwiftData @Query使用计算属性作为谓词崩溃问题
问题场景
定义了如下SwiftData模型:
@Model class Item: Identifiable, Hashable { @Attribute(.unique) let id = UUID() var start: Date? var end: Date? var isEnded: Bool { guard let end else { return false } return end < Date.now } init(start: Date?, end: Date?) { self.start = start self.end = end } }
在视图中使用@Query过滤该计算属性:
struct ItemsView: View { @Query( filter: #Predicate { $0.isEnded }, sort: [SortDescriptor(\Item.start)], animation: .bouncy ) private var items: [Item] // 视图其他代码... }
运行时直接崩溃,报错信息:
Thread 1: Fatal error: Couldn't find \Item.isEnded on Item with fields [SwiftData.Schema.PropertyMetadata(name: "id", keypath: \Item.id, defaultValue: Optional(6EB32774-0C93-4DB6-B338-DBB534CAE1F4), metadata: Optional(Attribute - name: , options: [unique], valueType: Any, defaultValue: nil, hashModifier: nil)), SwiftData.Schema.PropertyMetadata(name: "start", keypath: \Item.start, defaultValue: nil, metadata: nil), SwiftData.Schema.PropertyMetadata(name: "end", keypath: \Item.end, defaultValue: nil, metadata: nil), [...]
解答
是的,不能使用计算属性为SwiftData的@Query创建谓词。
原因很直接:SwiftData的@Query谓词是基于数据库中持久化的字段生成查询的,而计算属性isEnded不会被存储到数据库——从报错的Schema字段列表也能看到,只有id、start、end三个持久化属性,不存在isEnded。当SwiftData尝试把谓词转换为数据库查询语句时,找不到对应字段就会触发崩溃。
解决方法
把计算属性的逻辑直接写到谓词中,替换对isEnded的引用:
@Query( filter: #Predicate { guard let end = $0.end else { return false } return end < Date.now }, sort: [SortDescriptor(\Item.start)], animation: .bouncy ) private var items: [Item]
也可以简化为:
@Query( filter: #Predicate { $0.end != nil && $0.end! < Date.now }, sort: [SortDescriptor(\Item.start)], animation: .bouncy ) private var items: [Item]
这样SwiftData能识别到持久化的end字段,正常生成查询语句,不会再崩溃。
内容的提问来源于stackstack exchange,提问作者daniel
相关产品推荐
相关产品推荐

