UISearchbar 在 Swift 4 中使用 UItextfield

Posted

技术标签:

【中文标题】UISearchbar 在 Swift 4 中使用 UItextfield【英文标题】:UISearchbar using UItextfield in swift 4 【发布时间】:2018-11-01 11:33:33 【问题描述】:

我正在处理 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

【问题讨论】:

【参考方案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 中,您可以像下面这样使用.. 你的表视图如下

    创建项目 创建添加文本字段,tableView连接到viewcontroller

    添加以下代码..

     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 来在情节提要中创建此操作

【讨论】:

以上是关于UISearchbar 在 Swift 4 中使用 UItextfield的主要内容,如果未能解决你的问题,请参考以下文章

UISearchBar在Swift中完成后如何停止UIActivityIndi​​cator

如何在 Swift 中使用 UISearchBar 和 NSFetchedResultsController 在 Core Data 上一次获取多个实体?

Swift iOS 8+ UISearchBar图标,占位符和文本居中

使用 Swift 过滤 UISearchBar 的核心数据

如何在 Swift 中更改 UISearchBar 上的“取消”按钮的颜色

UISearchbar 并在查看控制器 xcode swift 中传递数据