英文:
How to resolve compiler error creating a SwiftData #Predicate?
问题
我一直在尝试多种方法来解决这个问题。我正在尝试使用谓词来获取 SwiftData 记录,但无论我尝试什么,都会导致一对错误:
初始化程序 'init(_:)' 要求 'Item' 遵循 'Encodable'
初始化程序 'init(_:)' 要求 'Item' 遵循 'Decodable'
这个错误是在扩展的 #Predicate
宏内部引发的。
这里是一个简单的类来演示这个问题:
@Model
final class Item {
@Attribute(.unique) var id: String
var timestamp: Date
init(timestamp: Date) {
self.id = UUID().uuidString
self.timestamp = timestamp
}
}
这里是导致编译器错误的简化代码:
extension Item {
static func foo() {
let item = Item(timestamp: .now)
let pred = #Predicate<Item> { $0.id == item.id }
}
}
我尝试了多种方法来解决这个错误。我看过的所有 Apple SwiftData 示例项目都没有出现这个错误。
我尝试遵循 Identifiable
协议。我尝试重命名 id
属性。我尝试直接将 id
类型更改为 UUID
,而不是 String
。
当然,我还添加了代码来遵循 Codable
协议。虽然这修复了编译器错误,但我最终遇到了运行时错误。请注意,Apple SwiftData 项目中的模型都没有遵循 Codable
协议。
我漏掉了什么?
英文:
I have been trying so many ways to resolve this issue. I am trying to fetch SwiftData records with a predicate. but everything I try results in a pair of errors:
>initializer 'init(_:)' requires that 'Item' conform to 'Encodable'
>initializer 'init(_:)' requires that 'Item' conform to 'Decodable'
The error is coming from within the expanded #Predicate
macro.
Here is a bare bones class to demonstrate the issue:
@Model
final class Item {
@Attribute(.unique) var id: String
var timestamp: Date
init(timestamp: Date) {
self.id = UUID().uuidString
self.timestamp = timestamp
}
}
And here is the bare bones code that causes the compiler issue:
extension Item {
static func foo() {
let item = Item(timestamp: .now)
let pred = #Predicate<Item> { $0.id == item.id }
}
}
I've tried so many ways to resolve this error. None of the Apple SwiftData sample projects I've seen give this error.
I've tried conforming to Identifiable
. I've renamed the id
property. I've changed the id
type to UUID
directly instead of String
.
And of course I've added code to conform to Codable
. While that fixed the compiler error, I ended up getting a runtime error. Note that none of the Apple SwiftData projects conform their models to Codable
.
What am I missing?
答案1
得分: 7
解决方法是避免在 #Predicate
闭包内引用模型对象。
只需将谓词行从:
let pred = #Predicate<Item> { $0.id == item.id }
更改为:
let anID = item.id
let pred = #Predicate<Item> { $0.id == anID }
虽然解决方法似乎很简单和明显,但错误很容易让您走入许多错误的路径。
英文:
The solution is to avoid referencing a model object inside the #Predicate
closure.
Simply change the predicate line from:
let pred = #Predicate<Item> { $0.id == item.id }
to:
let anID = item.id
let pred = #Predicate<Item> { $0.id == anID }
While the solution seems trivial and obvious, the error can easily lead you down many wrong paths.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论