Jon*_*s W 1 ios swift swiftui combine
我在 SwiftUI 代码中观察到一种奇怪的行为,并将其范围缩小到以下最小示例。
给定这个示例存储,其中包含书籍模型结构的数组。
struct Book: Identifiable {
let id: UUID
var likes: Int
var unusedProperty: String = ""
}
extension Book: Equatable {
static func == (lhs: Book, rhs: Book) -> Bool {
return lhs.id == rhs.id
}
}
class MyStorage: ObservableObject {
@Published var books: [Book] = [
.init(id: .init(uuidString: "B2A44450-BC03-47E6-85BE-E89EA69AF5AD")!, likes: 0),
.init(id: .init(uuidString: "F5AB9D18-DF73-433E-BB48-1C757CB6F8A7")!, likes: 0)
]
func addLike(to book: Book) {
for i in books.indices where books[i].id == book.id {
books[i].likes += 1
}
}
}
Run Code Online (Sandbox Code Playgroud)
并在这个简单的视图层次结构中使用它:
struct ReducedContentView: View {
@StateObject var storage: MyStorage = MyStorage()
var body: some View {
VStack(spacing: 8) {
ForEach(storage.books) { book in
HStack {
VStack(alignment: .leading) {
Text("Top-Level: \(book.likes)")
BookView(book: book)
}
Spacer()
Button("Add Like") {
storage.addLike(to: book)
}
}.padding(.horizontal)
}
}
}
}
struct BookView: View {
let book: Book
var body: some View {
Text("Nested: \(book.likes)")
.foregroundColor(.red)
}
}
Run Code Online (Sandbox Code Playgroud)
对属性的任何更改都likes不会传播到BookView,只会传播到“顶层” Text。
现在,如果我更改以下其中一项,它就会起作用:
unusedProperty(生产中需要的)&& lhs.likes == rhs.likes到 Equatable 一致性(这不是有意的)BookView为接受@Binding var book: Book而不是let最后一个选项是我可以在我的生产代码中采用的选项 - 尽管如此,我真的很想了解这里发生的情况,因此任何提示将不胜感激。
这是您的自定义一致性的结果Equatable:
extension Book: Equatable {
static func == (lhs: Book, rhs: Book) -> Bool {
return lhs.id == rhs.id
}
}
Run Code Online (Sandbox Code Playgroud)
如果删除它,它将按预期工作。
在您当前的代码中,您是说如果两个Books 具有相同的 ID,则它们是equal 的。我怀疑你实际上并不是说它们真正平等——你只是说它们是同一本书。
您的第二个选项(“添加&& lhs.likes == rhs.likes到Equatable一致性(这不是有意的)”)本质上只是使用Equatable系统生成的综合一致性,因为unusedProperty没有使用 - 所以,如果您要使用第二个选项,您也可以只需完全删除自定义==功能即可。
我认为这里要做的决定是你是否真的想告诉系统一个谎言(两个Books,无论它们的其他属性是什么,如果它们共享相同的属性,那么它们是相等的id),或者你是否应该让系统做它自己的工作告诉项目是否相等。
| 归档时间: |
|
| 查看次数: |
308 次 |
| 最近记录: |