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

Posted

技术标签:

【中文标题】弹出框在 ForEach 中显示不准确的信息【英文标题】:Popover displaying inaccurate information inside ForEach 【发布时间】:2021-02-07 00:52:28 【问题描述】:

我在 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: HStackText("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())
        
        
    

【问题讨论】:

【参考方案1】:

这是一个非常常见的问题(尤其是自 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: HStackText("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? 和@ 987654330@)。前者只是更惯用一点。

【讨论】:

可以确认,“isPresented”在 macOS 中只是被破坏了,而“item”几乎可以正常工作(有时只是什么都不做,但大部分时间都可以) 非常感谢。您的帮助是物有所值的!

以上是关于弹出框在 ForEach 中显示不准确的信息的主要内容,如果未能解决你的问题,请参考以下文章

弹出框在 IPAD 模拟器中透明但在设备中不透明

为啥故事板弹出框在 Swift 中的设备上不起作用?

Bootstrap 3 弹出框在“响应”模式下不起作用

弹出框在第一次悬停在图标上时不起作用

微信公众号弹出框在IOS最新系统中点击键盘上的“完成”导致事件无法触发问题

弹出框在状态栏中时的 NSPopover 瞬态