在ForEach中显示不准确信息的弹出窗口



我有一个问题,我有一个ForEach循环内的NavigationView。当我单击Edit按钮,然后单击每行右侧的铅笔图像时,我希望它显示我们在ForEach循环中使用的文本变量。但是,当我点击铅笔图像的文本,而不是test123,它仍然显示文本test123我完全不知道为什么。

这是一段视频。为什么会发生这种情况?

import SwiftUI
struct TestPopOver: View {

private var stringObjects = ["test123", "helloworld", "reddit"]

@State private var editMode: EditMode = .inactive
@State private var showThemeEditor = false

@ViewBuilder
var body: some View {
NavigationView {
List {
ForEach(self.stringObjects, id: .self) { text in
NavigationLink( destination: HStack{Text("Test!")}) {
HStack {
Text(text)
Spacer()
if self.editMode.isEditing {
Image(systemName: "pencil.circle").imageScale(.large)
.onTapGesture {
if self.editMode.isEditing {
self.showThemeEditor = true
}
}
}

}
}
.popover(isPresented: $showThemeEditor) {
CustomPopOver(isShowing: $showThemeEditor, text: text)
}

}
}
.navigationBarTitle("Reproduce Editing Bug!")
.navigationBarItems(leading: EditButton())
.environment(.editMode, $editMode)
}
}
}
struct CustomPopOver: View {
@Binding var isShowing: Bool
var text: String
var body: some View {
VStack(spacing: 0) {
HStack() {
Spacer()
Button("Cancel") {
self.isShowing = false
}.padding()
}
Divider()
List {
Section {
Text(text)
}
}.listStyle(GroupedListStyle())
}

}
}

这是一个非常常见的问题(特别是从iOS 14开始),在sheet中经常遇到,但也会影响popover

可以通过使用popover(item:)而不是isPresented来避免它。在这种情况下,它实际上会使用最新的值,而不仅仅是视图第一次呈现或第一次设置时出现的值。

struct EditItem : Identifiable { //this will tell it what sheet to present
var id = UUID()
var str : String
}
struct ContentView: View {

private var stringObjects = ["test123", "helloworld", "reddit"]

@State private var editMode: EditMode = .inactive
@State private var editItem : EditItem? //the currently presented sheet -- nil if no sheet is presented

@ViewBuilder
var body: some View {
NavigationView {
List {
ForEach(self.stringObjects, id: .self) { text in
NavigationLink( destination: HStack{Text("Test!")}) {
HStack {
Text(text)
Spacer()
if self.editMode.isEditing {
Image(systemName: "pencil.circle").imageScale(.large)
.onTapGesture {
if self.editMode.isEditing {
self.editItem = EditItem(str: text) //set the current item
}
}
}

}
}
.popover(item: $editItem) { item in //item is now a reference to the current item being presented
CustomPopOver(text: item.str)
}

}
}
.navigationBarTitle("Reproduce Editing Bug!")
.navigationBarItems(leading: EditButton())
.environment(.editMode, $editMode)
}.navigationViewStyle(StackNavigationViewStyle())
}
}
struct CustomPopOver: View {
@Environment(.presentationMode) private var presentationMode: Binding<PresentationMode>
var text: String
var body: some View {
VStack(spacing: 0) {
HStack() {
Spacer()
Button("Cancel") {
self.presentationMode.wrappedValue.dismiss()
}.padding()
}
Divider()
List {
Section {
Text(text)
}
}.listStyle(GroupedListStyle())
}

}
}

我还选择使用presentationMode环境属性来解散弹出窗口,但是可以传递editItem绑定并将其设置为nil(@Binding var editItem : EditItem?editItem = nil)。

最新更新