如何使用SwiftUI使用文本字段和动态foreach

mznpcxlj  于 2023-04-04  发布在  Swift
关注(0)|答案(1)|浏览(152)

我想在SwiftUI中开发一个类似HTML选择框的功能。
我写了如下代码。

let fruits : [String] = ["Apple", "Banana", "StrawBerry", "Grape", "Watermelon"]
    @State var searchText = ""
    var filterdFruits: [String] {
        fruits.filter {
            searchText.isEmpty ? true : $0.lowercased().contains(searchText.lowercased())
        }
}

VStack {
      TextField("Search ...", text: $searchText,onEditingChanged: { Bool in
           if Bool{
                 show = true
              }else{
                 show = false
              }
            }).onChange(of: searchText) {newValue in
                  show = true
           }
                    

       if show{
           ForEach(filterdFruits, id: \.self) { fruit in
              Text(fruit)
                .onTapGesture {
                   searchText =  fruit
                   show = false
                 }  
           }
       }
}

这个函数的目的是searchText应该有一个值。并且一些候选应该根据一个值出现。
但我有个问题。

当我在Foreach中选择一个项目时,searchText值会更新,并自动具有该值。
但是show变量不是假的。因为onChange方法被调用了。如果我删除onChange方法,在我在候选项中选择了一些东西之后,我删除了文本字段中的一些单词,并且没有更多的候选项。它应该在那里。

我的目标是,如果用户点击一个候选人,候选人视图将消失,然后searchText将具有相同的值。如果searchText正在删除,则应该有一些候选人在这里。
如何解决问题?

2hh7jdfx

2hh7jdfx1#

您的代码中的主要问题在于“onTapGesture”和“onchange”方法。代码“onTapGesture”在“onchange”代码之前执行,导致问题。但是,代码的正确执行应该是相反的。因此,我们需要在“onTapGesture”代码中添加位延迟,就像下面的代码一样,让“onchange”代码先执行。这样我们就可以解决您的问题。

struct Test: View {
    let fruits: [String] = ["Apple", "Banana", "StrawBerry", "Grape", "Watermelon"]
    @State var searchText = ""
    @State var show = false
    
    var filterdFruits: [String] {
        fruits.filter {
            searchText.isEmpty ? true : $0.lowercased().contains(searchText.lowercased())
        }
    }
    
    var body: some View {
        VStack {
            TextField("Search ...", text: $searchText, onEditingChanged: { editing in
                show = editing
            })
            .onChange(of: searchText) { _ in
                show = true
            }
            if show {
                ForEach(filterdFruits, id: \.self) { fruit in
                    Text(fruit)
                        .onTapGesture {
                            searchText = fruit
                            DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
                                show = false
                            }
                        }
                }
            }
        }
    }
}

如果你觉得理解代码有困难。请告诉我。我会很感激。谢谢

相关问题