【问题标题】:UISearchbar using UItextfield in swift 4UISearchbar 在 Swift 4 中使用 UItextfield
【发布时间】:2026-02-17 02:35:01
【问题描述】:

我正在处理 JSON。我的 Json 数据打印到 tableview 中。我想用搜索栏过滤这些数据。所以我把 Textfield 用于使用 Searchbar。我使用本网站的参考资料

http://findnerd.com/list/view/How-to-create-your-own-search-bar-in-Swift-Not-using-UISearchBar/20577/

我的搜索栏可以正常工作,但不能正常工作。我想在搜索栏中写 3 个单词后过滤数据。如果我写“Ku”,那么我的表格视图仍然隐藏。如果我在搜索栏中写“kus”,则搜索栏开始搜索并在表格视图中显示从“kus”开始的过滤数据。我的搜索栏相关代码是这些

struct PatientData:Decodable {
var ID : String
var dt_bod : String
var e_gender : String
var int_glcode : String
var var_email : String
var var_fname : String
var var_phoneno : String
var var_uname : String

init(userdata : [String:Any]) {
    self.ID = userdata["ID"] as! String
    self.dt_bod = userdata["dt_bod"] as! String
    self.e_gender = userdata["e_gender"] as! String
    self.int_glcode = userdata["int_glcode"] as! String
    self.var_email = userdata["var_email"] as! String
    self.var_fname = userdata["var_fname"] as! String
    self.var_phoneno = userdata["var_phoneno"] as! String
    self.var_uname = userdata["var_uname"] as! String

} 

var tabledata = [String]()
var tableFilterData = [String]()
var patientDetails = [PatientData]()

@IBAction func textfieldchanged(_ sender: Any) {
    tableview.isHidden = true
}

我的文本字段更改字符功能

public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool{

    let searchText  = textField.text! + string
    if searchText.count >= 3 {
        tableview.isHidden = false

        tableFilterData = tabledata.filter({ (result) -> Bool in
            return result.range(of: searchText, options: .caseInsensitive) != nil
        })

        print(tableFilterData)   // I got filtered data here but how to show this data into the tableview
        tableview.reloadData()
    }
    else{
        tableFilterData = []
    }
    return true
}

tableview部分是

 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return patientDetails.count
     }

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell:UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell") as UITableViewCell!

    let aa = patientDetails[indexPath.row].var_fname + " , " + patientDetails[indexPath.row].dt_bod + " , " + patientDetails[indexPath.row].var_phoneno

    self.tabledata.append(aa)

        cell.textLabel?.text = aa
        cell.textLabel?.font = searchTextfield.font

    return cell
}

【问题讨论】:

    标签: ios swift uisearchbar


    【解决方案1】:

    试试这个:

    @objc func textFieldActive() {
        tableView.isHidden = tableFilterData.count > 0 ? false : true
    }
    
    public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool{
    
        let searchText  = textField.text! + string
    
        if searchText.count >= 3 {
            tableView.isHidden = false
    
            tableFilterData = tabledata.filter({ (result) -> Bool in
                return result.range(of: searchText, options: .caseInsensitive) != nil
            })
    
            tableView.reloadData()
        }
        else{
            tableFilterData = []
        }
    
        return true
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection 
    section: Int) -> Int {
        return tableFilterData.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let data = tableFilterData[indexPath.row]
    
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
    
        cell.textLabel?.text = data
    
        return cell
    }
    

    【讨论】:

    • 三字tableview正常工作后没有显示过滤数据>
    • 需要将过滤后的数据设置为tableView dataSource,而不是原来的tableData
    • 你的鲸鱼 :)
    • 先生,我根据您的代码编辑了我的代码,还做了一些更改。我将我的 json 数据放入结构中并显示在 tableview 中。现在我得到过滤的数据,但如何显示到 tableview 是问题。请帮帮我。
    • 您使用patientDetails作为tableView数据源,它非常简单,您需要将表格视图的数据源设置为您想要显示的内容,因为在这种情况下您正在过滤,您应该将 tableView 数据源设置为结构的过滤版本
    【解决方案2】:

    在 Swift 4 或 Swift 5 中,您可以像下面这样使用.. 你的表视图如下

    1. 创建项目
    2. 创建添加文本字段,tableView连接到viewcontroller
    3. 添加以下代码..

       class ViewController: UIViewController ,UITableViewDelegate,UITableViewDataSource,UITextFieldDelegate{
      
        @IBOutlet weak var tableView: UITableView!
        @IBOutlet weak var txtName: UITextField!
      
        var originalArr = [[String:Any]]();
        var searchArrRes = [[String:Any]]()
        var searching:Bool = false
      
       override func viewDidLoad() {
          super.viewDidLoad()
      
          //Assign delegate  don't forget
          txtName.delegate = self
          tableView.delegate = self
          tableView.dataSource = self
      
         //my array
        originalArr =   [
          ["name": "abdul", "number": "+8800000001"],
          ["name": "abdin", "number": "+8800000002"],
          ["name": "Enamul", "number": "+8800000003"],
          ["name": "enam", "number": "+8800000004"],
          ["name": "Rafi", "number": "+8800000005"],
          ["name": "Ehaque", "number": "+8800000006"],
          ["name": "ab", "number": "+8800000007"],
          ["name": "Emon", "number": "+8800000008"],
          ["name": "enamu1", "number": "+8800000009"],
          ["name": "rafi", "number": "+88000000010"],
          ["name": "karim", "number": "+88000000011"],
          ["name": "radev", "number": "+88000000012"],
          ["name": "da", "number": "+88000000013"],
          ["name": "aa", "number": "+88000000014"],
          ["name": "rafi", "number": "+88000000010"],
          ["name": "karim", "number": "+88000000011"],
          ["name": "radev", "number": "+88000000012"],
          ["name": "da", "number": "+88000000013"],
          ["name": "aa", "number": "+88000000014"]
         ]
      
      }
      
      
      func textFieldShouldReturn(_ textField: UITextField) -> Bool {
         textField.resignFirstResponder()
         return true
      }
      
       public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool{
         //input text
         let searchText  = textField.text! + string
        //add matching text to arrya
         searchArrRes = self.originalArr.filter({(($0["name"] as! String).localizedCaseInsensitiveContains(searchText))})
      
        if(searchArrRes.count == 0){
          searching = false
        }else{
          searching = true
       }
        self.tableView.reloadData();
      
        return true
      }
      
      
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
         //check search text & original text
         if( searching == true){
            return searchArrRes.count
         }else{
            return originalArr.count
         }
       }
      
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        //custom cell Custom_cell
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! Custom_cell
        //check search text & original text
         if( searching == true){
          var dict = searchArrRes[indexPath.row]
          cell.label_name.text = dict["name"] as? String
          cell.label_number.text = dict["number"] as? String
        }else{
          var dict = originalArr[indexPath.row]
          cell.label_name.text = dict["name"] as? String
          cell.label_number.text = dict["number"] as? String
      
       }
      
        return cell
      }
      
      
      }
      

    您可以从 GitHub 链接下载完整源代码:https://github.com/enamul95/TableView_Search

    【讨论】:

    • 参考您的帖子答案,如果可能的话,我可以问一个与 tableView 搜索相关的问题吗?
    【解决方案3】:

    您可以在过滤之前检查文本的大小:

    public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool{
    
        var searchText  = textField.text! + string
    
        if string  == "" {
            searchText = (searchText as String).substring(to: searchText.index(before: searchText.endIndex))
        }
        if searchText == "" {
            isSearch = false
            tableview.reloadData()
        }
        else{
            if searchText.count > 2 {
               getSearchArrayContains(searchText)
            }  
        }
        return true
    }
    

    【讨论】:

    • 我已经尝试过了,但是没有用。编辑此代码后,当我在搜索栏中编写第一个单词时,它显示所有未过滤的数据,并且在我编写第二个单词后,tableview 隐藏和搜索栏不起作用。
    • 为什么不使用导航栏的UISearchBar
    • 我用 UISearchBar 完成了这个。但是现在写我的任务是用 UITextfield 做这些事情。
    【解决方案4】:

    请使用此代码:-

    func getSearchArrayContains(_ text : String) {
    
        tableFilterData = tableData.filter({$0.lowercased().contains(text)})
        isSearch = true
         tableview.reloadData()
    }
    

    如果三个字符使用这个链接enter link description here:-

    谢谢

    【讨论】:

      【解决方案5】:

      以上所有答案都试图通过将更改连接到前一个字符串来对UITextField 字符串进行逆向工程。之所以需要这样做,是因为在对 UITextField 字符串进行更改之前调用了委托方法 shouldChangeCharactersIn

      这些实现是错误的,并且当用户向左滚动光标并继续输入或选择并替换文本时不起作用(因为答案忽略了NSRange 委托变量)。

      更好的实现是根本不使用委托方法,而是将目标添加到UITextField。这是因为UITextField 继承自UIControl

      override func viewDidLoad() {
          super.viewDidLoad()
          searchTextField.addTarget(self, action: #selector(searchTextChanged(_:)), for: .editingChanged)
      }
      
      @objc func searchTextChanged(_ sender: UITextField) {
          let search = sender.text ?? ""
          filterContentForSearchText(search)
      }
      
      func filterContentForSearchText(_ searchText: String) {
          print("Filterin with:", searchText)
          filtered.removeAll()
          filtered = original.filter { thing in
              return "\(thing.value.lowercased())".contains(searchText.lowercased())
          }
          tableView.reloadData()
      }
      

      注意:也可以通过创建@IBAction 并将Editing Changed 连接从UITextField 拖到@IBAction 来在情节提要中创建此操作

      【讨论】: