UISearchResultsUpdating 不基于 searchBar 文本过滤 collectionView

Posted

技术标签:

【中文标题】UISearchResultsUpdating 不基于 searchBar 文本过滤 collectionView【英文标题】:UISearchResultsUpdating not filtering collectionView based on searchBar text 【发布时间】:2017-09-19 01:47:26 【问题描述】:

我正在尝试根据 searchBar 文本输入过滤 collectionView。我能够在 textDidChange 和 updateSearchResults 函数调用上使用数据库中的所有用户加载和填充 UISearchResultsUpdating 类的 collectionView,但 collectionView 不会根据 searchBar 输入进行过滤(它始终显示数据库中的所有用户 - 即使在文本输入上) .我认为棘手的部分是我有一个集合视图(菜单栏类),它委托给其他 2 个集合视图。这些 collectionView 中的每一个都有不同的 searchBar 和 searchController。请参阅随附的屏幕截图和代码以供参考。提前致谢!

// 带有两个 searchControllers 的 searchVC

class SearchVC: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UISearchControllerDelegate, UISearchBarDelegate 

    var users = [CurrentTraveler]()
    var isSearching = false
    var filteredData = [CurrentTraveler]()

    var peopleResultsViewController: SearchPeopleResultsVC?

    var filtered:[String] = []
    var searchActive : Bool = false
    var searchPeopleController: UISearchController?

    let cellId1 = "cellId1"
    let cellId2 = "cellId2"

    override func viewDidLoad() 
        super.viewDidLoad()         
        setupSearchBar()
        setupCollectionView()
    

    func setupSearchBar() 
        // sets up searchBar for first collectionView...
    

    func setupCollectionView() 
        contentCollectionView.dataSource = self
        contentCollectionView.delegate = self
        contentCollectionView.register(SearchPeopleCollectionView.self, forCellWithReuseIdentifier: cellId2)
    

    func scrollToMenuIndex(menuIndex: Int) 
        let indexPath = IndexPath(item: menuIndex, section: 0)
        contentCollectionView.scrollToItem(at: indexPath, at: UICollectionViewScrollPosition(), animated: true)

        if indexPath.item == 1 
            searchPeopleController?.delegate = self
            searchPeopleController?.searchBar.delegate = self

            peopleResultsViewController = SearchPeopleResultsVC()

            searchPeopleController = UISearchController(searchResultsController: peopleResultsViewController)
            searchPeopleController?.searchResultsUpdater = peopleResultsViewController

            navigationItem.titleView = searchPeopleController?.searchBar
        

        if indexPath.item == 0 
            // sets up searchController for first collectionView search
        
    

//menubar collectionView
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return 2
    

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId1", for: indexPath) 

        if indexPath.item == 0 
            // set up first collectionView in menubar...
        

        if indexPath.item == 1 
            let usersCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId2", for: indexPath) as! SearchPeopleCollectionView
            usersCell.searchVC = self
            return usersCell
        
        return cell
    

    var filterString = "" 
        didSet 
            guard filterString != oldValue else  return 

            if filterString.isEmpty 
                filteredData = users
            
            else 
                filteredData = users.filter  ($0.name?.localizedStandardContains(filterString))! 
            
            peopleResultsViewController?.collectionView.reloadData()
        
    

    func updateSearchResults(for searchPeopleController: UISearchController) 
        filterString = searchPeopleController.searchBar.text ?? ""

        if filterString.isEmpty 
            filteredData = users
        
        else 
            filteredData = users.filter  ($0.name?.localizedStandardContains(filterString))! 
        
        peopleResultsViewController?.collectionView.reloadData()
    

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 
      // should I do anything here...?  
    


// UISearchResults更新类

class SearchPeopleResultsVC : UIViewController, UISearchResultsUpdating, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UISearchBarDelegate 

    let cellId = "cellId"

    var users = [CurrentTraveler]()
    var filteredData = [CurrentTraveler]()
    var isSearching = false
    var searchVC: SearchVC?
    var peopleResultsViewController: SearchPeopleResultsVC?
    var searchController: UISearchController?
    var searchPeopleCollectionView: SearchPeopleCollectionView?
    var filtered:[String] = []
    var searchActive : Bool = false

    let searchPeopleController = UISearchController(searchResultsController: nil)

    lazy var collectionView: UICollectionView = 
        cv.dataSource = self
        cv.delegate = self
        return cv
    ()

    override func viewDidLoad() 
        collectionView.delegate = self
        collectionView.dataSource = self

        fetchTravelingUserCell()
    

    func fetchTravelingUserCell() 
        Database.database().reference().child("users").observe(.childAdded, with:  (snapshot) in

            if let dictionary = snapshot.value as? [String: AnyObject] 
                let user = CurrentTraveler(dictionary: dictionary)
                self.users.append(user)

                DispatchQueue.main.async(execute: 
                    self.collectionView.reloadData()
                )
            
        , withCancel: nil)
    

    var filterString = "" 
        didSet 
            // Return if the filter string hasn't changed.
            guard filterString != oldValue else  return 

            if filterString.isEmpty 
                filteredData = users
            
            else 
                filteredData = users.filter  ($0.name?.localizedStandardContains(filterString))! 
            
            collectionView.reloadData()
        
    

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        if searchPeopleController.isActive && searchPeopleController.searchBar.text != "" 
            return filteredData.count
        
        return users.count
    


    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as? BaseGlobalSearchUser else  fatalError("Expected to display a `DataItemCollectionViewCell`.") 

        if searchPeopleController.isActive && searchPeopleController.searchBar.text != "" 
            cell.currentTraveler = filteredData[indexPath.item]
         else 
            cell.currentTraveler = users[indexPath.item]
        
        return cell
    

    func updateSearchResults(for searchPeopleController: UISearchController) 
        filterString = searchPeopleController.searchBar.text ?? ""
// does print what user types in the searchBar        
print(filterString)

        if filterString.isEmpty 
            filteredData = users
        
        else 
            filteredData = users.filter  ($0.name?.localizedStandardContains(filterString))! 
        
        peopleResultsViewController?.collectionView.reloadData()
    

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 
        if filterString.isEmpty 
            filteredData = users
        
        else 
            filteredData = users.filter  ($0.name?.localizedStandardContains(filterString))! 
        
        self.collectionView.reloadData()
    


//数据模型类

class CurrentTraveler: SafeJsonObject 

    var name: String?
    var profileImageUrl: String?
    var travelingPlace: String?

    init(dictionary: [String: AnyObject]) 
        super.init()

        self.name = dictionary["name"] as? String
        self.profileImageUrl = dictionary["profileImageUrl"] as? String
        self.travelingPlace = dictionary["users/uid/Places"] as? String
        setValuesForKeys(dictionary)
    

【问题讨论】:

【参考方案1】:

可能是您的filteredString 为空。所以你没有得到价值。

所以尝试如下:

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 
    if filterString.isEmpty 
        filterString = searchText
    
    if filterString.isEmpty 
        filteredData = users
     else 
        filteredData = users.filter  ($0.name?.localizedStandardContains(filterString))! 
    
    self.collectionView.reloadData()

【讨论】:

以上是关于UISearchResultsUpdating 不基于 searchBar 文本过滤 collectionView的主要内容,如果未能解决你的问题,请参考以下文章

如何使 UITableViewController 符合协议 UISearchResultsUpdating?

为啥使用 UISearchResultsUpdating 取消按钮后我的 tableview 是空白的?

Swift:如何对数组中结构的子值使用 UISearchResultsUpdating?

代码实现搜索框

UISearchControllerDelegate - 搜索栏在表头中不可见

UISearchController 很坑