【问题标题】:Swift 3/4: SearchBar not filtering results properly in TableViewSwift 3/4:SearchBar 未在 TableView 中正确过滤结果
【发布时间】:2018-04-20 06:37:36
【问题描述】:

我有一个弹出窗口,顶部是 searchBar,下面是 TableView。 TableView 由动态数据填充。我有一个自定义 tableViewCell,带有一个名称标签和一个复选框(M13CheckBox Library)来选择一个名称。

现在,当我搜索名称时,首先 tableView 没有加载,因为用户在搜索栏中输入了名称。例如,假设有名为“Mary”、“Mackenzie”、“Margaret”和“Mallory 的人”。我想搜索“Margaret”,所以我开始在 searchBar 中输入“Mar”,然后是“Mary”和“ Margaret”在 tableView 中被正确过滤,但是当我返回时,即“Ma”,那么它应该显示所有 4 个名字,因为“Ma”是存在于列表中,但 tableView 不显示任何内容。

因此,如果名称中包含字母,则 tableView 应始终在用户在 searchBar 中键入时重新加载。请帮我解决这个问题。由于它是一个弹出窗口,我通过通知将数据从另一个 VC 传递给 tableView。 这是我的搜索 VC 代码:

class ParticipantsListVC: UIViewController, UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate{

public static var participantNameArray:[String] = [String]()         //global var
var viewController: ViewController!

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.delegate = self
    tableView.dataSource = self
    searchParticipantFilter.delegate = self

    viewController = ViewController()

    let notificationName = NSNotification.Name("reloadList")       
    NotificationCenter.default.addObserver(forName: notificationName, object: nil, queue: OperationQueue.main) { (notifObject) in
        self.tableView.reloadData()
    }
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText:String) {
    if searchText == "" {
        ParticipantsListVC.participantNameArray.removeAll()
        viewController.getParticipantList()         // func to get list from sever
    }else{           
        ParticipantsListVC.participantNameArray = ParticipantsListVC.participantNameArray.filter({(name) -> Bool in                
            return name.lowercased().contains(searchText.lowercased())
        })            
    }
    self.tableView.reloadData()
  }
}

此外,如果我选择了一个名称,则在该名称前面选择了复选框。但是当我单击 searchBar 中的取消(X)时,tableView 中的第一个单元格始终显示为选中状态,而不是我选择的名称.我不知道为什么在从过滤列表中选择名称后总是选择第一个单元格。

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

    let dict = ParticipantsListVC.participantNameArray[indexPath.row]
    cell.participantNameLabel.text = dict

    if selectedIndexPaths.contains(indexPath) {
        cell.selectedParticipantCB.setCheckState(.checked, animated: true)
    }else{
        cell.selectedParticipantCB.setCheckState(.unchecked, animated: true)
    }
    return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    // Since any random cell was getting selected on scrolling So I added this code. 
    tableView.deselectRow(at: indexPath, animated: true)           
    if selectedIndexPaths.contains(indexPath) {
        selectedIndexPaths.removeObject(object: indexPath)            
    }else{
        selectedIndexPaths.append(indexPath)
    }
    tableView.reloadData()
}

我不想在 headerView 或其他 tableView 中使用 searchBar 来显示过滤列表。非常感谢。谢谢。

【问题讨论】:

    标签: ios swift tableview uisearchbar nsnotificationcenter


    【解决方案1】:

    您需要创建另一个数组来保存数据数组的备份。

    var arrParticipantList = [String]()
    var arrParticipantListBackup = [String]()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        self.searchBar.delegate = self
        self.tblParticipantList.delegate = self
        self.tblParticipantList.dataSource = self
        self.arrParticipantList = ["Mary", "Mackenzie", "Margaret", "Mallory","Molly"]
        self.arrParticipantListBackup = self.arrParticipantList
    }
    

    用于搜索搜索字符串、重新填充数组和重新加载 tableview 的代码

    extension ViewController: UISearchBarDelegate {
    
        func searchBar(_ searchBar: UISearchBar, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    
            var searchText = searchBar.text! + text
            if range.length > 0 {
    
                if range.location == 0 {
    
                    self.arrParticipantList = self.arrParticipantListBackup
                    self.tblParticipantList.reloadData()
                    return true
                }
                searchText = String(searchText.dropLast(range.length))
            }
            self.arrParticipantList = self.arrParticipantListBackup.filter({$0.lowercased().hasPrefix(searchText.lowercased())})
            self.tblParticipantList.reloadData()
            return true
        }
    
        func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
    
            self.searchBar.text = ""
            self.searchBar.resignFirstResponder()
            self.arrParticipantList = self.arrParticipantListBackup
            self.tblParticipantList.reloadData()
        }
    }
    

    表格视图代码

    extension ViewController: UITableViewDelegate, UITableViewDataSource {
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    
            return self.arrParticipantList.count
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
            cell?.textLabel?.text = self.arrParticipantList[indexPath.row]
            return cell!
        }
    }
    

    希望这能解决您的问题。

    【讨论】:

      【解决方案2】:
      struct namelist {
      
          var searchname: NSString
      
      }
      
      var searchActive = Bool()
      var newSearchArray = [namelist]()
      
      func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                return searchActive ? newSearchArray.count  : nameOldArray.count
      
          }
      
          func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
      
              let Cell:SearchTableViewCell! = tableView.dequeueReusableCell(withIdentifier: "Cell") as! SearchTableViewCell
              Cell.selectionStyle = .none
      
              if (searchActive == true) {
      
                  if ( newSearchArray.count > 0) {
      
                      var para = NSMutableAttributedString()
                      para = NSMutableAttributedString(string:(newSearchArray[indexPath.row].searchname) as String)
      
                  do {
      
                      let regex = try NSRegularExpression(pattern: searchText, options: NSRegularExpression.Options.caseInsensitive )
                      let nsstr = newSearchArray[indexPath.row].searchname
                      text = nsstr as String
                      let all = NSRange(location: 0, length: nsstr.length)
                      var matches : [String] = [String]()
                      regex.enumerateMatches(in: text, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: all) {
      
                          (result : NSTextCheckingResult?, _, _) in
      
                          if let r = result {
      
                              let results = nsstr.substring(with: r.range) as String
                              matches.append(results)
                              let substringrange = result!.rangeAt(0)
                              para.addAttribute(NSForegroundColorAttributeName, value:UIColor.init(red: 237/255.0, green: 60/255.0, blue: 58/255.0, alpha: 1.0), range: substringrange)
                              Cell.namelbl.attributedText = para
                          }
                      }
      
                  } catch {
      
                   }
      
                  }
              }
              else {
      
                  Cell.namelbl.text = self.searchname[indexPath.row] as? String
              }
              return Cell
      
          }
      
      func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
      
               searchArray.removeAllObjects()
              newSearchArray.removeAll()
      
              if Search.text != nil {
      
                  for i in 0 ..< searchname.count {
      
                      searchText = Search.text!
                      text = ((searchname.object(at: i))) as! String
      
                      if text.lowercased().contains(searchText.lowercased()) {
      
                          let elm = namelist(searchname: text as NSString)
                          self.newSearchArray.append(elm)
                      }
      
      
      
                  }
      
              }
               searchActive = !newSearchArray.isEmpty
               searchBar.resignFirstResponder()
               yourTableName.reloadData()
      
          }
      

      【讨论】:

      • 嗨!你有同样的问题吗??
      • 这里struct namelist有什么用
      • 我没有任何问题。这是您问题的解决方案@Bella
      • 我已经使用结构来过滤名称@Anbu.karthik
      • 你试过了吗@Bella
      猜你喜欢
      • 2020-06-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-03
      • 1970-01-01
      相关资源
      最近更新 更多