在SwiftUI中使用TextField难以更新字符串

时间:2020-04-09 00:51:10

标签: swift swiftui textfield

我目前无法使用TextField修改String值。到目前为止,这是我的(简化)代码:

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)
    }
}

我似乎无法使用TextField修改GradeItem对象的名称。编辑TextField时,其文本临时更改。但是,重新加载GradeItemRow视图时,它将显示GradeItem对象的原始名称,而不是其更新名称。

请问有人可以帮忙吗?

预先感谢

更新:根据您的请求,我已将此示例代码添加了更多上下文。

我知道这是行不通的,因为当我尝试使用TextField修改GradeItem的名称时,它会暂时更改。但是,当我选择其他课程,然后又选择了最初的课程时,TextField将显示未修改的名称值。

1 个答案:

答案 0 :(得分:0)

以下测试有效。

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])
        }
    }
}