视图更新期间我要修改什么状态?

时间:2019-09-11 15:29:29

标签: ios swift swiftui

我有一个CoreData对象Day,我正在此视图中编辑该对象,在“编辑”模式下,该卡允许一个Picker视图,然后一个TextField以允许用户输入。这些都按预期工作,但是,当我点击运行“ saveEditToDay()”功能的“ done”时,该功能只是将其保存到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;
     }
}

1 个答案:

答案 0 :(得分:0)

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