SwiftUI:只能编辑 ForEach 列表中的第一项
SwiftUI: Can only Edit the first item in a ForEach List
我在 Core Data 中保存了一个书签列表。当我尝试单击特定书签的编辑按钮时,无论我选择哪个书签,只有列表中第一个书签的值会填满编辑中的文本字段sheet。
这是 macOS 10.15 应用程序。
内容视图
@State private var showEditView = false
ForEach(vm.myBookmarks) { myBookmark in
Text(myBookmark.name)
Text(myBookmark.url)
Button {
showEditView = true
} label: {
Image("pencil")
}
.sheet(isPresented: $showEditView) {
EditBookmarkView(name: myBookmark.name, url: myBookmark.url, isVisible: $showEditView, bm: myBookmark)
}
}
编辑书签视图
struct EditBookmarkView: View {
@Environment(\.presentationMode) var presentationMode
@Binding var isVisible: Bool
@ObservedObject var vm: EditBookmarkViewModel
let name: String
let url: String
var bm: MyBookmarkViewModel
init(name: String, url: String, isVisible: Binding<Bool>, bm: MyBookmarkViewModel) {
self.bm = bm
self.vm = EditBookmarkViewModel(bookmarkVM: bm)
_isVisible = isVisible
self.name = name
self.url = url
}
var body: some View {
TextField("Edit Name", text: $vm.name)
Spacer()
TextField("Edit url", text: $vm.url)
Button("Update") {
vm.save()
}
}
}
您为 ForEach
中的每个项目创建一个 sheet,并且一次只能表示一个 sheet。因此 showEditView
显示与层次结构中第一个视图相关的 sheet,它又捕获列表中的第一个项目。
您可以使用接受项目绑定的 sheet
:当项目不是 nil
时显示 sheet。您只需要一个这样的 sheet,因此将其添加到您的列表中,而不是每个项目中。
完成编辑后,将 selectedBookmark
设置为 nil
以隐藏 sheet。
完整的工作示例:
struct Bookmark: Identifiable {
let id: Int
}
struct ContentView: View {
@State private var selectedBookmark: Bookmark?
let items = (0..<10).map { Bookmark(id: [=10=]) }
var body: some View {
ForEach(items) { myBookmark in
HStack {
Text(String(describing: myBookmark))
Button {
selectedBookmark = myBookmark
} label: {
Image(systemName: "pencil").foregroundColor(.red)
}
}
}
.sheet(item: $selectedBookmark) { selectedBookmark in
let _ = print(String(describing: selectedBookmark))
Text(String(describing: selectedBookmark))
}
}
}
我在 Core Data 中保存了一个书签列表。当我尝试单击特定书签的编辑按钮时,无论我选择哪个书签,只有列表中第一个书签的值会填满编辑中的文本字段sheet。
这是 macOS 10.15 应用程序。
内容视图
@State private var showEditView = false
ForEach(vm.myBookmarks) { myBookmark in
Text(myBookmark.name)
Text(myBookmark.url)
Button {
showEditView = true
} label: {
Image("pencil")
}
.sheet(isPresented: $showEditView) {
EditBookmarkView(name: myBookmark.name, url: myBookmark.url, isVisible: $showEditView, bm: myBookmark)
}
}
编辑书签视图
struct EditBookmarkView: View {
@Environment(\.presentationMode) var presentationMode
@Binding var isVisible: Bool
@ObservedObject var vm: EditBookmarkViewModel
let name: String
let url: String
var bm: MyBookmarkViewModel
init(name: String, url: String, isVisible: Binding<Bool>, bm: MyBookmarkViewModel) {
self.bm = bm
self.vm = EditBookmarkViewModel(bookmarkVM: bm)
_isVisible = isVisible
self.name = name
self.url = url
}
var body: some View {
TextField("Edit Name", text: $vm.name)
Spacer()
TextField("Edit url", text: $vm.url)
Button("Update") {
vm.save()
}
}
}
您为 ForEach
中的每个项目创建一个 sheet,并且一次只能表示一个 sheet。因此 showEditView
显示与层次结构中第一个视图相关的 sheet,它又捕获列表中的第一个项目。
您可以使用接受项目绑定的 sheet
:当项目不是 nil
时显示 sheet。您只需要一个这样的 sheet,因此将其添加到您的列表中,而不是每个项目中。
完成编辑后,将 selectedBookmark
设置为 nil
以隐藏 sheet。
完整的工作示例:
struct Bookmark: Identifiable {
let id: Int
}
struct ContentView: View {
@State private var selectedBookmark: Bookmark?
let items = (0..<10).map { Bookmark(id: [=10=]) }
var body: some View {
ForEach(items) { myBookmark in
HStack {
Text(String(describing: myBookmark))
Button {
selectedBookmark = myBookmark
} label: {
Image(systemName: "pencil").foregroundColor(.red)
}
}
}
.sheet(item: $selectedBookmark) { selectedBookmark in
let _ = print(String(describing: selectedBookmark))
Text(String(describing: selectedBookmark))
}
}
}