弹出窗口在 ForEach 中显示不准确的信息
Popover displaying inaccurate information inside ForEach
我遇到了一个问题,我在 NavigationView 中有一个 ForEach 循环。当我单击“编辑”按钮,然后单击每行右侧的铅笔图像时,我希望它显示我们在 ForEach 循环中使用的文本变量。但是当我点击 test123 以外的文本的铅笔图像时,它仍然显示文本 test123 我完全不知道为什么。
Here's一个视频。为什么会这样?
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
)。前者只是更地道一点。
我遇到了一个问题,我在 NavigationView 中有一个 ForEach 循环。当我单击“编辑”按钮,然后单击每行右侧的铅笔图像时,我希望它显示我们在 ForEach 循环中使用的文本变量。但是当我点击 test123 以外的文本的铅笔图像时,它仍然显示文本 test123 我完全不知道为什么。
Here's一个视频。为什么会这样?
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
)。前者只是更地道一点。