swiftui 中的自动完成搜索不起作用

问题描述

我有一个 TextField 作为搜索框。我想让它自动搜索,即每当我在 TextField 中输入一个字母时,我应该不用按回车键就能得到结果。这是我的代码

TextField("Search",text: $searchText,onEditingChanged: {
        isEditing in
        print("isEditing")
        //my method to fetch result
    },onCommit: {
        print("onCommit")
    })

但它不是那样工作的。在文本字段中输入一个字母后,当我按下回车键时,它首先打印“onCommit”,然后打印“isEditing”。知道如何让它工作吗?

解决方法

你可以试试这样的:

TextField("Search",text: Binding(
    get: { searchText },set: { newVal in
    searchText = newVal
    // my method to fetch result
}))
,

但是,您可以考虑使用这种替代方法来创建搜索框:

let langDictionary: [String:String] = [
    "af"  :  "Afrikaans","al"  :  "Albanian","ar"  :  "Arabic","az"  :  "Azerbaijani","bg"  :  "Bulgarian","ca"  :  "Catalan","cz"  :  "Czech","da"  :  "Danish","de"  :  "German","el"  :  "Greek","en"  :  "English","eu"  :  "Basque","fa"  :  "Persian (Farsi)","fi"  :  "Finnish","fr"  :  "French","gl"  :  "Galician","he"  :  "Hebrew","hi"  :  "Hindi","hr"  :  "Croatian","hu"  :  "Hungarian","id"  :  "Indonesian","it"  :  "Italian","ja"  :  "Japanese","kr"  :  "Korean","la"  :  "Latvian","lt"  :  "Lithuanian","mk"  :  "Macedonian","no"  :  "Norwegian","nl"  :  "Dutch","pl"  :  "Polish","pt"  :  "Portuguese","pt_br"  :  "Portuguese (Brazil)","ro"  :  "Romanian","ru"  :  "Russian","se"  :  "Swedish","sk"  :  "Slovak","sl"  :  "Slovenian","es"  :  "Spanish","sr"  :  "Serbian","th"  :  "Thai","tr"  :  "Turkish","uk"  :  "Ukrainian","vi"  :  "Vietnamese","zh_cn"  :  "Chinese Simplified","zh_tw" :   "Chinese Traditional","zu"  :  "Zulu"]


struct ContentView: View {
    @State var searchQuery = ""
    @State var langArr = Array(langDictionary.values.sorted {$0 < $1})
    
    var body: some View {
        VStack (spacing: 30)  {
            TextField("Search",text: $searchQuery).padding(10)
                .overlay(RoundedRectangle(cornerRadius: 15).stroke(Color.blue,lineWidth: 1))
                .foregroundColor(.blue)
            
            ScrollView {
                VStack(spacing: 10) {
                    // move the search system here
                    ForEach(langArr.filter{self.searchFor($0)}.sorted(by: { $0 < $1 }),id: \.self) { lang in
                        Text(lang).padding(10)
                    }
                }
            }
        }.padding(10)
    }
    
    private func searchFor(_ txt: String) -> Bool {
        return (txt.lowercased(with: .current).hasPrefix(searchQuery.trim().lowercased(with: .current)) || searchQuery.trim().isEmpty)
    }
}
,

在您的情况下,我想使用Combine 框架的Just 订阅者。请查看 .onReceive 部分以了解。这是经过测试的代码。 Just 是一个发布者,它只向每个订阅者发出一次输出,然后完成。

因此,当它检测到更改时,它会发布并.onReceiver 捕获该更改。

import SwiftUI
import Combine

struct TestView: View {
    @State var searchText: String = ""
    
    var body: some View {
        VStack {
            TextField("Search",text: $searchText,onEditingChanged: {
                    isEditing in
                    print("isEditing")
                    //my method to fetch result
                },onCommit: {
                    print("onCommit")
                })
                .onReceive(Just(searchText),perform: { _ in
                    if searchText.count > 0 {
                        print("Text entered: \(searchText). Now do whatever you want")
                    }
                })
        }
    }
}