Сложность обновления строки с помощью TextField в SwiftUI - PullRequest
0 голосов
/ 09 апреля 2020

В настоящее время у меня возникают проблемы при изменении значения String с использованием TextField. Вот мой (упрощенный) код:

class GradeItem: ObservableObject {

    @Published var name: String
    @Published var scoredPoints: Double
    @Published var totalPoints: Double
    let isUserCreated: Bool

    init(name: String, scoredPoints: Double, totalPoints: Double, isUserCreated: Bool) {
        self.name = name
        self.scoredPoints = scoredPoints
        self.totalPoints = totalPoints
        self.isUserCreated = isUserCreated
    }
}

var courses: [Course] {
    // initialization code...
}

struct GradeCalculatorView: View {

    @State var selectedCourseIndex: Int = 0

    var body: some View {
        VStack {
            // allows user to select a course:
            ForEach(0 ..< courses.count) { i in
                Button(action: {
                    self.selectedCourseIndex = i
                }, label: {
                    Text(courses[i].name)
                })
            }
            CourseView(course: courses[selectedCourseIndex])
        }
    }
}

struct CourseView: View {

    @ObservedObject var course: Course   // passed in from GradeCalculatorView

    var body: some View {
        VStack(alignment: .leading) {
            Text(course.name)
            ForEach(course.categories, id: \.name) { category in
                GradeCategoryView(category: category)
            }
        }.padding(.leading).frame(alignment: .leading)
    }
}

struct GradeCategoryView: View {

    @ObservedObject var category: GradeCategory   // passed in from CourseView

    var body: some View {

        VStack(alignment: HorizontalAlignment.leading) {

            HStack {
                Text(category.name)
                Spacer()
            }

            ForEach(category.items, id:\.name) { item in
                GradeItemRow(item: item)
            }
        }
    }
}

struct GradeItemRow: View {

    @ObservedObject var item: GradeItem   // passed in from GradeCategoryView

    var body: some View {
        TextField("Item Name", text: $item.name)
    }
}

Я не могу изменить имя объекта GradeItem с помощью TextField. Когда TextField редактируется, его текст временно изменяется. Однако, когда представление GradeItemRow перезагружается, оно отображает оригинальное имя объекта GradeItem, а не его обновленное имя.

Может ли кто-нибудь помочь?

Заранее спасибо

ОБНОВЛЕНИЕ: согласно вашим запросам, я добавил больше контекста в этот пример кода.

Я знаю, что это не работает, поскольку, когда я пытаюсь изменить имя GradeItem с помощью TextField, оно временно изменяется. Однако, когда я выбираю другой курс, а затем курс, на котором я был изначально, TextField отображает неизмененное значение имени.

1 Ответ

0 голосов
/ 10 апреля 2020

Следующий тест работает.

class GradeItem: ObservableObject {

@Published var name: String
@Published var scoredPoints: Double
@Published var totalPoints: Double
let isUserCreated: Bool

init(name: String, scoredPoints: Double, totalPoints: Double, isUserCreated: Bool) {
    self.name = name
    self.scoredPoints = scoredPoints
    self.totalPoints = totalPoints
    self.isUserCreated = isUserCreated
}

init() {
    self.name = "gradeItem" + UUID().uuidString
    self.scoredPoints = 0.0
    self.totalPoints = 0.0
    self.isUserCreated = false
}
}

class Course: ObservableObject {
@Published var name: String
@Published var categories: [GradeCategory]
init(name: String, categories: [GradeCategory]) {
    self.name = name
    self.categories = categories
}
init() {
    self.name = "course_" + UUID().uuidString
    self.categories = [GradeCategory]()
    self.categories.append(GradeCategory())
}
}

class GradeCategory: ObservableObject {
@Published var name: String
@Published var items: [GradeItem]
init(name: String, items: [GradeItem]) {
    self.name = name
    self.items = items
}
init() {
    self.name = "category_" + UUID().uuidString
    self.items = [GradeItem]()
    self.items.append(GradeItem())
}
}

struct GradeItemRow: View {
@ObservedObject var item: GradeItem   // passed in from GradeCategoryView

var body: some View {
    TextField("Item Name", text: $item.name).textFieldStyle(RoundedBorderTextFieldStyle())
}
}

struct GradeCategoryView: View {
@ObservedObject var category: GradeCategory   // passed in from CourseView

var body: some View {
    VStack(alignment: .leading) {
        HStack {
            Text(category.name)
            Spacer()
        }
        ForEach(category.items, id: \.name) { item in
            GradeItemRow(item: item)
        }
    }
}
}

struct CourseView: View {
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
@ObservedObject var course: Course   // passed in from ContentView

var body: some View {
    VStack(alignment: .leading) {
        Button(action: {
            self.presentationMode.wrappedValue.dismiss()
        }, label: {
            Text("done")
        })
        Spacer()
        Text(course.name)
        ForEach(course.categories, id: \.name) { category in
            GradeCategoryView(category: category)
        }
        Spacer()
    }.padding(.leading).frame(alignment: .leading)
}
}

struct ContentView: View {
@State var courses: [Course] = [Course(), Course()]
@State var selectedCourseIndex: Int = 0
@State var showCourse = false

var body: some View {
    VStack {
        ForEach(0 ..< courses.count) { i in
            Button(action: {
                self.selectedCourseIndex = i
                self.showCourse = true
            }, label: {
                Text(self.courses[i].name)
            })
        }
    }.sheet(isPresented: self.$showCourse) {
        CourseView(course: self.courses[self.selectedCourseIndex])
    }
}
}
...