mih*_*ema 3 swift swiftui swiftui-list swiftui-sheet
简短描述:在详细视图中,我有一个相关实体的列表。对于每个项目,都有一个按钮可打开该项目的编辑表。
List {
if (book.booksBorrowers != nil) {
ForEach (Array(book.booksBorrowers! as! Set<Borrowers>), id: \.self) { borrower in
HStack {
Text(borrower.firstName ?? "unbekannter Vorname")
Text(borrower.lastName ?? "unbekannter Nachname")
Text(String(format: "%.0f", borrower.age))
Spacer()
Button {
showingBorrowerEditScreen.toggle()
} label: {
Image(systemName: "pencil")
.frame(width: 20.0, height: 20.0)
}.multilineTextAlignment(.center).buttonStyle(.borderless)
.sheet(isPresented: $showingBorrowerEditScreen) {
EditBorrowerView(
aBorrower: borrower,
firstName: borrower.firstName!,
lastName: borrower.lastName!,
age: Int(borrower.age)
).environment(\.managedObjectContext, self.viewContext)
}
}
}.onDelete(perform: deleteBorrower)
}
}.listStyle(.inset(alternatesRowBackgrounds: true))
Run Code Online (Sandbox Code Playgroud)
单击列表中的某个编辑按钮后,会出现一张带有编辑表单的工作表,其中预填充了所选列表项的值。
struct EditBorrowerView: View {
@Environment(\.managedObjectContext) var moc
@Environment(\.dismiss) var dismiss
@State private var firstName = ""
@State private var lastName = ""
@State private var age = 0.0
@StateObject var aBorrower: Borrowers
init(aBorrower: Borrowers, firstName: String, lastName: String, age: Int) {
self._aBorrower = StateObject(wrappedValue: aBorrower)
self._firstName = State(initialValue: aBorrower.firstName ?? "")
self._lastName = State(initialValue: aBorrower.lastName ?? "")
self._age = State(initialValue: Double(aBorrower.age))
}
let formatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.minimumFractionDigits = 0
formatter.maximumFractionDigits = 0
return formatter
}()
var body: some View {
VStack {
Text("Ausleiher bearbeiten").font(.title)
Form {
VStack {
TextField("Vorname", text: $firstName)
TextField("Nachname", text: $lastName)
HStack {
Slider(value: $age, in: 0...99, step: 1)
TextField("Alter", value: $age, formatter: formatter)
}
}
}
HStack {
Button("Save") {
// save the edited book
aBorrower.firstName = firstName
aBorrower.lastName = lastName
aBorrower.age = Double(age)
try? moc.save()
dismiss()
}
Button("Cancel") {
dismiss()
}
}
}.padding(10)
}
}
Run Code Online (Sandbox Code Playgroud)
但是现在,当单击一行的编辑按钮时
使用 print() 进行的小型调试显示,单击编辑按钮时,首先设置正确的值(例如,我单击第三项,传递第三项的值),但此外,所有列表项也传递到工作表。
如果视图中有一个.sheet(isPresented:)在循环中重复的修改器,但布尔状态变量位于循环之外,则该状态变量将用于工作表的多个副本。有时,这可能会表现为一张工作表,其中显示的详细信息与您单击的行不同;有时您可能会看到多张纸。听起来您所看到的副作用与此有关。
有几种方法可以解决这个问题。
sheet(item:)将您替换showingBorrowerEditScreen为borrowerToEdit可选对象的状态变量,默认为 nil:
@State private var borrowerToEdit: Borrower? = nil
Run Code Online (Sandbox Code Playgroud)
在按钮操作中,将其设置为循环中当前行的借用者:
Button {
borrowerToEdit = borrower
} label: {
// etc
Run Code Online (Sandbox Code Playgroud)
最后,在循环外item:使用sheet修饰符的形式。请注意,此形式采用一个块,其中包含对相关借用者对象的引用。ForEach
ForEach(...) { borrower in
// etc.
}
.sheet(item: $borrowerToEdit) { borrower in
EditBorrowerView(
aBorrower: borrower,
firstName: borrower.firstName!,
lastName: borrower.lastName!,
age: Int(borrower.age)
)
}
Run Code Online (Sandbox Code Playgroud)
如果您想坚持使用布尔值来表示是否应使用模式表,则需要通过提取行详细信息将该布尔值隔离到其自己的子视图。例如:
List {
if (book.booksBorrowers != nil) {
ForEach (Array(book.booksBorrowers! as! Set<Borrowers>), id: \.self) { borrower in
BorrowerListRow(borrower: borrower)
.onDelete(perform: deleteBorrower)
}
}
}
struct BorrowerListRow: View {
@ObservedObject var borrower: Borrower
@State private var showingBorrowerEditScreen = false
var body: some View {
HStack {
Text(borrower.firstName ?? "unbekannter Vorname")
Text(borrower.lastName ?? "unbekannter Nachname")
Text(String(format: "%.0f", borrower.age))
Spacer()
Button {
showingBorrowerEditScreen.toggle()
} label: {
Image(systemName: "pencil")
.frame(width: 20.0, height: 20.0)
}.multilineTextAlignment(.center).buttonStyle(.borderless)
.sheet(isPresented: $showingBorrowerEditScreen) {
EditBorrowerView(
aBorrower: borrower,
firstName: borrower.firstName!,
lastName: borrower.lastName!,
age: Int(borrower.age)
).environment(\.managedObjectContext, self.viewContext)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这样,每一行都有自己的“我是否应该显示模式”布尔值,因此不会混淆哪一行“拥有”活动工作表,并且一次只能显示一个。
您选择哪个选项部分取决于个人喜好。我倾向于在我自己的代码中选择选项 1,因为感觉模式更多地是由列表而不是一行“拥有”的,并且它强化了您一次只能编辑一个借款人的想法。但无论哪种方法都应该消除您当前遇到的问题。
| 归档时间: |
|
| 查看次数: |
844 次 |
| 最近记录: |