【发布时间】:2021-10-03 17:16:28
【问题描述】:
以下是我绘制 SwiftUI 视图的代码,该视图使用发布者获取需要在列表中绘制的项目。这些项目都具有使用Toggle 绘制的布尔值。
我的视图是愚蠢的,所以我可以使用任何类型的布尔值,也许支持 UserDefaults、支持核心数据,或者只是某个地方的布尔属性......无论如何,当在视图之外更新布尔值时,这不会重绘其中一个布尔值已更新。
onReceive 被调用,我可以在控制台中看到输出更改,但绑定不是我的 ToggleItem 结构的一部分,因此 SwiftUI 不会重绘。
我的代码...
我有一个类似这样的结构,注意这里的绑定类型...
struct ToggleItem: Identifiable, Equatable {
let id: String
let name: String
let isOn: Binding<Bool>
public static func == (lhs: ToggleItem, rhs: ToggleItem) -> Bool {
lhs.id == rhs.id
}
}
在我的 SwiftUI 中,我有这个...
struct MyView: View {
@State private var items: [ToggleItem] = []
let itemsPublisher: AnyPublisher<[ToggleItem], Never>
// ...
var body: some View {
List {
// ...
}
.onReceive(itemsPublisher) { newItems in
print("New items: \(newItems)")
items.removeAll() // hacky redraw
items = newItems
}
}
我可以看到这里发生了什么,因为 Binding<Bool> 不是一个值,所以 SwiftUI 看到 newItems 的数组等于它已经绘制的 items,因此,这不会重绘。
我是否缺少一些东西,也许是一些巧妙的 SwiftUI/Combine 为我重绘了这个?
【问题讨论】:
-
目前还不清楚究竟是什么没有被重绘。你能创建一个最小可重复的例子吗?不相关,但在数据模型中拥有
Binding<Bool>属性是没有意义的——它应该只是Bool——然后你在视图中创建一个绑定来更新它。 -
问题是因为 ToggleItem 类型的
Equatable函数,因为您刚刚使用id来寻找尊重!你也必须让他们所有人参与!那么它将起作用。或者完全删除 == 函数 xCode 将构建一个内部 == 函数,该函数也可以以这种方式工作,但您至少必须符合Equatable!跨度> -
@swiftPunk 这是一个不错的建议,但在更新到
lhs.id == rhs.id && lhs.isOn.wrappedValue == rhs.isOn.wrappedValue时似乎不起作用,这是您的意思吗? -
@NewDev 我认为绑定也是问题,烦人的是我试图保持我的视图抽象,所以它不知道特定类型,但想通过改变来避免有两个事实来源它是一个简单的
Bool,我的想法是绑定会包装一个事实来源 - 有没有更好的方法来做到这一点?