開(kāi)始用Swift開(kāi)發(fā)iOS 10 - 18 Search Bar 和 UISearchController


上一篇 開(kāi)始用Swift開(kāi)發(fā)iOS 10 - 17 使用Core Data 是使用Core Data存儲(chǔ)數(shù)據(jù),這一篇是添加搜索功能。

使用 UISearchController

UISearchController是一個(gè)簡(jiǎn)潔的創(chuàng)建搜索條和管理搜索結(jié)果的API。
通常情況下,為以table為基礎(chǔ)的app添加搜索條只需要下面三行代碼就可以了,searchResultsControllernil時(shí)搜索結(jié)果顯示就在當(dāng)前搜索的頁(yè)面以當(dāng)前的樣式顯示。

searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
tableView.tableHeaderView = searchController.searchBar

為我的FoodPin應(yīng)用添加搜索條:

  • RestaurantTableViewController中添加一個(gè)變量:

     var searchController: UISearchController!
    
  • viewDidLoad中初始化:

      searchController = UISearchController(searchResultsController: nil)
      tableView.tableHeaderView = searchController.searchBar
    

這樣就添加了搜索條,但還每天添加搜索邏輯,搜索沒(méi)效。

篩選內(nèi)容

  • RestaurantTableViewController中繼續(xù)添加一個(gè)變量,用戶存儲(chǔ)篩選結(jié)果:

    var searchResults: [RestaurantMO] = []
    
  • 添加篩選方法:

      func filterContent(for searchText: String) {
          searchResults = restaurants.filter({
          (restaurant) -> Bool in
              
              if let name = restaurant.name {
                  let isMatch = name.localizedCaseInsensitiveContains(searchText)
                  return isMatch
              }
              return false
          })
      }
    

filter是數(shù)組的一個(gè)方法,它遍歷數(shù)組的每一項(xiàng)進(jìn)行閉包中的操作,根據(jù)結(jié)果判斷是否刪除對(duì)應(yīng)項(xiàng),最后得到一個(gè)篩選的數(shù)組。
localizedCaseInsensitiveContains方法用來(lái)判斷name中是否包含searchText(忽略大小寫(xiě))

更新搜索結(jié)果

  • RestaurantTableViewController “符合” UISearchResultsUpdating協(xié)議:

    class RestaurantTableViewController: UITableViewController, NSFetchedResultsControllerDelegate, UISearchResultsUpdating
    
  • 實(shí)現(xiàn)UISearchResultsUpdating協(xié)議:
    中的updateSearchResults(for:)方法,這個(gè)方法在搜索條被選則和輸入搜索字時(shí)調(diào)用:

    func updateSearchResults(for searchController: UISearchController) {
        if let searchText = searchController.searchBar.text {
            filterContent(for: searchText)
            tableView.reloadData()
        }
    }
  • 更新tableView(_:numberOfRowsInSection:)UISearchController有一個(gè)isActive屬性用來(lái)判斷搜索控制器當(dāng)前活躍狀態(tài)。
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if searchController.isActive {
            return searchResults.count
        } else {
            return restaurants.count
        }
    }
  • 更新tableView(_:cellForRowAt:)。根據(jù)UISearchController的狀態(tài)判斷是從restaurants中獲取數(shù)據(jù)還是searchResults
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cellIdentifier = "Cell"
        let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier,
                                                 for: indexPath) as! RestaurantTableViewCell
        
        let restaurant = (searchController.isActive) ? searchResults[indexPath.row] : restaurants[indexPath.row]
        
        cell.nameLabel.text = restaurant.name
        cell.thumbnailImageView.image = UIImage(data: restaurant.image! as Data)
        cell.thumbnailImageView.layer.cornerRadius = 30.0
        cell.thumbnailImageView.clipsToBounds = true
        cell.locationLabel.text = restaurant.location
        cell.typeLabel.text = restaurant.type
        cell.accessoryType = restaurant.isVisited ? .checkmark: .none
        
        return cell
    }
  • 實(shí)現(xiàn)一個(gè)新的方法,讓table在搜索狀態(tài)下不可以滑動(dòng)編輯。
    override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        if searchController.isActive {
            return false
        } else {
            return true
        }
    }
  • 更新prepare(for:),讓segue在傳輸數(shù)據(jù)到detail view時(shí)的數(shù)據(jù)也相對(duì)應(yīng)。

      destinationController.restaurant = searchController.isActive ? searchResults[indexPath.row] : restaurants[indexPath.row
    
  • viewDidLoad中添加兩行代碼:

searchController.searchResultsUpdater = self
searchController.dimsBackgroundDuringPresentation = false

現(xiàn)在就完成了搜索功能。

定制搜索條的樣式

UISearchBar提供一些屬性用來(lái)定制。在viewDidLoad中添加:

searchController.searchBar.placeholder = "Search restaurants..."
searchController.searchBar.tintColor = UIColor.white
searchController.searchBar.barTintColor = UIColor(red: 218.0/255.0, green:
100.0/255.0, blue: 70.0/255.0, alpha: 1.0)

Exercise:添加地址搜索

只需要更改搜索函數(shù)filterContent

searchResults = restaurants.filter({
        (restaurant) -> Bool in
            
            if let name = restaurant.name, let location = restaurant.location {
                let isMatchName = name.localizedCaseInsensitiveContains(searchText)
                let isMatchLocation = location.localizedCaseInsensitiveContains(searchText)
                if isMatchName || isMatchLocation {
                    return true
                }
                
            }
            return false
        })

代碼

Beginning-iOS-Programming-with-Swift

說(shuō)明

此文是學(xué)習(xí)appcode網(wǎng)站出的一本書(shū) 《Beginning iOS 10 Programming with Swift》 的一篇記錄

系列文章目錄

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容