简体   繁体   English

将@State 绑定到同一结构中的可选@Binding SwiftUI

[英]Bind @State to optional @Binding in the same struct SwiftUI

I am creating a View that may or may not receive a binding:我正在创建一个可能会或可能不会收到绑定的视图:


import SwiftUI

struct AssignmentEditMenu: View {
    
    @EnvironmentObject var planner: Planner
    @Environment(\.dismiss) var dismiss
    
    var isEditing // set to true if assignment is not nil
    var assignment: Binding<Assignment>?
        
    @State var newAssignment = assignment ?? Assignment()
    // if assignment is not nil, create a copy of it and set newAssignment equal to the copy
    // if assignment is nil, initialize a new struct and set newAssignment equal to it
    
    var body: some View {
        
        NavigationView {
            Form {
                nameSection
                dateSection
            }
            .navigationTitle(Text("New Assignment"))
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button(isEditing ? "Add" : "Done") {
                        isEditing ? (assignment = newAssignment) : planner.addAssignment(newAssignment)
                        dismiss()
                    }
                }
                ToolbarItem(placement: .navigationBarLeading) {
                    Button("Cancel") {
                        dismiss()
                    }
                }
            }
        }
    }
    
    var nameSection: some View {
        Section {
            TextField("Name", text: $newAssignment.name)
            Picker("Course", selection: $newAssignment.course) {
                ForEach(planner.courses) { course in
                    Text("\(course.name)").tag(course)
                }
                
            }
        }
    }
    
    var dateSection: some View {
        Section {
            DatePicker(
                selection: $newAssignment.assignedDate,
                displayedComponents: [.date, .hourAndMinute]
            ) {
                Text("Assigned:")
                    .lineLimit(1)
                    .allowsTightening(true)
            }
            DatePicker(
                selection: $newAssignment.dueDate
            ) {
                Text("Due:")
                    .lineLimit(1)
                    .allowsTightening(true)
            }
        }
    }
}

What I am trying to do is if a binding to an Assignment is passed in here, then the View is in Edit Mode.我想要做的是,如果在此处传递了对Assignment的绑定,则视图处于编辑模式。 newAssignment will be set to the same values as the assignment binding but not reference it at all. newAssignment将被设置为与assignment绑定相同的值,但根本不引用它。 It will collect changes and when complete, set that assignment binding equal to itself, thus saving the changes.它将收集更改并在完成后将assignment绑定设置为等于自身,从而保存更改。 The reason for using newAssignment is so that if the user cancels (this view will be a sheet) changes are discarded since newAssignment is a @State var.使用newAssignment的原因是,如果用户取消(此视图将是一张工作表)更改将被丢弃,因为newAssignment是一个 @State 变量。

When no Assignment binding is passed in the View is in Create mode.当没有传递任何Assignment绑定时,视图处于创建模式。 newAssignment collects the changes and is added to the store via planner . newAssignment收集更改并通过planner添加到商店。

Assignment implementation: Assignment实现:


struct Assignment: Identifiable, Equatable, Hashable  {
    var name: String
    var assignedDate: Date
    var dueDate: Date
    var course: Course
    var percentCompleted: Double
    let id: UUID
    
    init(
        name: String = "",
        assignedDate: Date = Date(),
        dueDate: Date = Calendar.current.nextDate(after: Date(), matching: .init(hour: 0, minute: 0), matchingPolicy: .strict)!,
        course: Course = Course()
    ) {
        self.name = name
        self.assignedDate = assignedDate
        self.dueDate = dueDate
        self.course = course
        self.id = UUID()
        self.percentCompleted = 0.0
    }
}

struct Course: Identifiable, Equatable, Hashable {
    var name: String
    let id: UUID
    
    init(_ name: String = "Course") {
        self.name = name
        self.id = UUID()
    }
}

Add a custom init.添加自定义初始化。 With that, newAssignment var is also not needed.这样,也不需要newAssignment var。

struct AssignmentEditMenu: View {
    
    @EnvironmentObject var planner: Planner
    @Environment(\.dismiss) var dismiss
    
    var isEditing // set to true if assignment is not nil

   var assignment: Binding<Assignment>
    
    init(a: Binding<Assignment> = .constant(Assignment())) {
        assignment = a 
    }

.....

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM