【问题标题】:What state am I modifying during view update?在视图更新期间我要修改什么状态?
【发布时间】:2019-09-15 17:01:17
【问题描述】:

我有一个 CoreData 对象 Day 在此视图中进行编辑,当处于“编辑”模式时,卡片允许 Picker 视图和 TextField 允许用户输入。这些都按预期工作,但是当我点击运行saveEditToDay() 函数的“完成”时,它只是将这些保存到Day 变量中。这与Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1cffc77e0) 崩溃并给出提示Modifying state during view update, this will cause undefined behavior.。我不清楚在这种情况下我修改了什么状态?

这里是视图:


import SwiftUI

struct EditCard: View {

    @Binding var day: Day?
    var timeOfDay: Time
    @State var isEditing: Bool = false
    @State var selectedRating = 0
    @State var description = ""
    var ratings = Rating.getAllRatings()

    // MARK: - Body
    var body: some View {
        VStack(alignment: .leading) {
            HStack {
                Text(timeOfDay.rawValue).font(.headline)
                Spacer()
                Button(action: {
                    if self.isEditing { self.saveEditToDay() }
                    self.isEditing.toggle()
                }, label: { self.isEditing ? Text("Done") : Text("Edit") })
                    .foregroundColor(Color("PrimaryColour"))
            }

            Divider()

            VStack(alignment: .leading) {
                Text("RATING")
                    .font(.caption)
                    .foregroundColor(Color(UIColor.systemGray))

                if isEditing {
                    Picker(selection: $selectedRating, label: Text("")) {
                        ForEach(0 ..< ratings.count) {
                            Text(self.ratings[$0]).tag([$0])
                        }
                    }
                } else {
                    Text(day!.getRating(for: timeOfDay))
                }

            }.padding(.trailing)

            VStack(alignment: .leading) {
                Text("REASON")
                   .font(.caption)
                   .foregroundColor(Color(UIColor.systemGray))

                if isEditing {
                    TextField(description, text: $description)
                } else {
                    Text(description)
                       .multilineTextAlignment(.leading)
                       .lineLimit(nil)
                }

           }
        }
        .padding()
        .background(Color(UIColor.secondarySystemGroupedBackground))
        .cornerRadius(10)
        .onAppear { self.setSelected() }
        .onDisappear{ self.saveEditToDay(); print("Toodles") }
    }

    // MARK: - Functions
    func setSelected() {
        guard let day = day else { return }
        self.selectedRating = ratings.firstIndex(of: day.getRating(for: timeOfDay))!
        self.description = day.getDescription(for: timeOfDay)
    }

    func saveEditToDay() {
        guard let day = day else { return }
        day.setRating(rating: ratings[selectedRating], for: timeOfDay)
        day.setDescription(description: description, for: timeOfDay)
    }
}

这里是我正在调用的 NSManagedObject 的扩展:

func setRating(rating: String, for time: Time) {
     switch time {
     case .morning: self.morning = rating;
     case .afternoon: self.afternoon = rating;
     case .evening: self.evening = rating;
     }
}

func setDescription(description: String, for time: Time) {
     switch time {
     case .morning: self.morningDescription = description;
     case .afternoon: self.afternoonDescription = description;
     case .evening: self.eveningDescription = description;
     }
}

【问题讨论】:

    标签: ios swift swiftui


    【解决方案1】:

    您在onApear() 中调用setSelected(),这会修改您标记为@State 的两个变量:selectedRatingdescription。这意味着当视图被绘制或重绘时,您正在更改定义在过程中途绘制的内容的变量。 onApear() 是触发后台刷新的好地方,但不要立即修改任何 @State 变量。 您可能应该编写一个初始化程序来绑定到 DayTime 设置其他两个变量,就像您在 setSelected() 中所做的那样。

    【讨论】:

    • This article 声明onAppear() 是更改@State 变量的安全 位置。了解为什么会出现这种差异?
    猜你喜欢
    • 2022-11-13
    • 2019-12-17
    • 2020-06-12
    • 1970-01-01
    • 2017-07-31
    • 2020-03-11
    • 2020-05-15
    • 2021-09-17
    • 1970-01-01
    相关资源
    最近更新 更多