【发布时间】:2021-06-01 16:59:44
【问题描述】:
为什么我的视图在更新完成之前呈现模型更新?或者至少看起来是这样。看起来,它是根据我的模型以前的值重新绘制的。
我在做什么:当您点击一个人单元格时,它会将那个人标记为“已选中”,然后将前景色更改为绿色。如果未选中,则前景色为白色。
发生了什么:重要的是要注意这并不总是会发生。似乎是随机的。但偶尔,当我点击一个人的单元格时,颜色不会改变。而且我已经深入挖掘,那是因为它(看起来)在我的 PeopleStore 模型对象中的值发生变化之前重绘了视图。
代码如下:
struct PersonCell: View {
@EnvironmentObject var peopleStore: PeopleStore
var personId: UUID
var person: Person {
return peopleStore.people.filter({ $0.id == personId }).first!
}
var body: some View {
Button(action: {
print("Tapped Cell: " + peopleStore.personName(id: personId))
peopleStore.toggleSelectionOfPerson(with: personId)
}) {
GeometryReader { geo in
ZStack {
Rectangle().foregroundColor(peopleStore.personIsSelected(id: personId) ? .tGreen : .white).cornerRadius(geo.size.width / 2).frame(height: 70)
当我点击一个单元格时会发生以下情况:
class PeopleStore: ObservableObject {
@Published var people : [Person]
init(people: [Person]){
self.people = people
}
func personIsSelected(id: UUID) -> Bool {
let index = people.firstIndex(where: { $0.id == id })!
print("ZSTACK: \(people[index].name) is selected: \(people[index].isSelected.description)")
return people[index].isSelected
}
func toggleSelectionOfPerson(with id: UUID) {
let index = people.firstIndex(where: { $0.id == id })!
print("BEFORE \(people[index].name) is selected: \(people[index].isSelected.description)")
people[index].isSelected = !people[index].isSelected
print("AFTER \(people[index].name) is selected: \(people[index].isSelected.description)")
}
当我查看我的控制台时,您可以看到在我选择一个人后,视图会重新绘制,但它具有以前的值(在这种情况下,我点击了 Alexandra 单元格):
Tapped Cell: Alexandra R.
BEFORE Alexandra R. is selected: false
ZSTACK: Jose G. is selected: false
ZSTACK: Jimmy T. is selected: false
ZSTACK: Alexandra R. is selected: false
ZSTACK: Dominic R. is selected: false
AFTER Alexandra R. is selected: true
ZSTACK: Franny E. is selected: false
ZSTACK: Jon B. is selected: true
ZStack:在重新绘制单元格时打印。如您所见,Alexandra 被选中:出现 false,而我认为它是 true。
重新抽签的时间似乎有点偏,而且似乎是随机的。我错过了什么?
编辑:人员结构
struct Person: Identifiable {
let id = UUID()
var name: String
var photo: Image
var isFavorite: Bool
var dateFavorited = Date()
var isSelected: Bool = false
}
编辑 2:如果有帮助,PersonCell 是称为 PersonList 的子视图,它使用 ForEach 生成 PersonCell。
struct PeopleList: View {
@EnvironmentObject var peopleStore: PeopleStore
var title: String {
return isFavorites ? "Favorites" : "All Employees"
}
var isFavorites: Bool
var body: some View {
LazyVStack(alignment: .leading, spacing: 15) {
Text(title).padding(.top, 18).padding(.horizontal, 5).font(.regular())
if isFavorites {
ForEach(peopleStore.people.sorted(by: { $0.dateFavorited < $1.dateFavorited }).filter({ $0.isFavorite })) { person in
PersonCell(personId: person.id).frame(height: 70.0)
}
【问题讨论】:
-
“它会在我的 PeopleStore 模型对象中的值更改之前重绘视图”,订阅的视图只有在发布者触发属性更改更新时才会重绘。您的代码中肯定发生了其他事情,我认为您需要分享更多细节。
-
我添加了 Person 结构。如果有帮助,则人员单元格是称为 PersonList 的子视图,它使用 ForEach 生成 PersonCells。
-
PeopleList 中也有 EnvironmentObject,当您单击 ChildCell 中的按钮并更新模型中的属性时,PeopleList 视图也会刷新。
-
您是否提出了替代方案?
-
这可能是
person到titlevcomputed 属性。因为您每次访问该属性时都在过滤。如果body重绘和触发器之间的时间以及过滤所需的时间,它不会在访问时重新计算变化。