在Swift中搜索TableView

时间:2017-01-15 16:10:27

标签: arrays swift uitableview tableview uisearchbar

我有两个数组:FirstTableArray(包括品牌名称)和SecondTableArray(包括模型)。

我想添加搜索功能,可以通过名称的一部分找到手机型号。

import UIKit
import MessageUI

class FirstTableViewController: UITableViewController {

    var FirstTableArray = [String]()
    var SecondTableArray = [SecondTable]()

override func viewDidLoad() {

    super.viewDidLoad()

    self.navigationController?.navigationBar.isTranslucent = false
    self.navigationController?.navigationBar.barStyle = .black
    self.navigationController?.navigationBar.tintColor = UIColor.white

// First Table Array

    FirstTableArray = ["Apple", "Samsung"]

// Second Table Array

    SecondTableArray = [
    SecondTable(SecondTitle: ["iPhone 5s", "iPhone 6", "iPhone 6s"]),
    SecondTable(SecondTitle: ["Galaxy S4", "Galaxy S5", "Galaxy S6"]), 
    ]   
    }

 override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
    return FirstTableArray.count
    }

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let Cell = self.tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as UITableViewCell
    Cell.textLabel?.text = FirstTableArray[(indexPath as NSIndexPath).row]
    return Cell
    }

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let indexPath : IndexPath = self.tableView.indexPathForSelectedRow!
    let DestViewController = segue.destination as! SecondTableViewController
    let SecondTableArrayTwo = SecondTableArray[(indexPath as NSIndexPath).row]
    DestViewController.SecondTableArray = SecondTableArrayTwo.SecondTitle
    } 
}

你能帮我解决这个问题吗?

2 个答案:

答案 0 :(得分:47)

我今天正在做同样的事情,发现本教程非常容易理解:https://github.com/codepath/ios_guides/wiki/Search-Bar-Guide

它将指导您完成在Interface Builder中添加搜索栏,设置委托以及包含过滤结果的方法的步骤。

在iOS项目中,为用户提供搜索项目集合的方法是一项相当常见的任务。用于实现搜索行为的标准界面是搜索栏。

使用搜索栏有几种常用方法:

  • 直接使用UISearchBar。这是最简单的使用方法 UISearchBars。如果你想设计,这可以非常灵活 并编写自己的搜索界面,但不提供 许多内置功能与其他方法一样。

  • 使用UISearchDisplayController帮助管理搜索界面。 UISearchDisplayController允许您呈现标准搜索 与内置动画的界面。此方法强制您显示 在表格视图中搜索结果。 - 已弃用

  • 使用UISearchController帮助管理搜索界面。该
    UISearchController是一个较新的控制器(仅在iOS 8+中可用)
    这有助于您使用任何类型的视图呈现搜索界面 显示搜索结果。

本指南介绍了使用这些类的基本知识。这些类都没有实际实现"搜索"查找与给定查询字符串匹配的项目的行为,因为确定哪些对象匹配将根据特定于域的用例而变化(例如,当搜索"人员#34;您可能希望仅匹配他们的名称,而您可能想要在搜索电子邮件时进行全文预索引搜索。您必须自己实施任何搜索/过滤行为。

直接使用UISearchBars

在其核心,搜索栏只不过是一个美化的文本字段,其中包含范围控件和一些动画以及几个按钮。每个搜索栏都有一个委托,使您有机会响应用户操作。最重要的委托方法是:

  • textDidChange - 大部分时间您都会通过此方式回复此事件 在用户键入时更新显示的搜索结果集 查询
  • searchBarSearchButtonClicked - 在某些情况下是搜索操作 很慢(例如需要进行慢速API调用),你会想要等待 直到用户在更新搜索之前点击搜索按钮 结果。

搜索表格的示例

我们从一个带有基本UITableView的视图应用程序开始。您可以像在任何其他控件中一样添加UISearchBar,方法是将其拖放到界面构建器中的视图控制器或通过编程方式添加它。

搜索栏的委托属性必须设置为实现UISearchBarDelegate的对象。通常,您使视图控制器实现UISearchBarDelegate并在viewDidLoad方法中设置searchBar.delegate = self。

enter image description here

实现搜索行为的代码如下。我们维护一个额外的数组filteredData来表示与我们的搜索文本匹配的数据行。当搜索文本更改时,我们更新filteredData并重新加载我们的表。

class ViewController: UIViewController, UITableViewDataSource, UISearchBarDelegate {
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var searchBar: UISearchBar!

let data = ["New York, NY", "Los Angeles, CA", "Chicago, IL", "Houston, TX",
    "Philadelphia, PA", "Phoenix, AZ", "San Diego, CA", "San Antonio, TX",
    "Dallas, TX", "Detroit, MI", "San Jose, CA", "Indianapolis, IN",
    "Jacksonville, FL", "San Francisco, CA", "Columbus, OH", "Austin, TX",
    "Memphis, TN", "Baltimore, MD", "Charlotte, ND", "Fort Worth, TX"]

var filteredData: [String]!

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.dataSource = self
    searchBar.delegate = self
    filteredData = data
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "TableCell", for: indexPath) as UITableViewCell
    cell.textLabel?.text = filteredData[indexPath.row]
    return cell
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return filteredData.count
}

// This method updates filteredData based on the text in the Search Box
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    // When there is no text, filteredData is the same as the original data
    // When user has entered text into the search box
    // Use the filter method to iterate over all items in the data array
    // For each item, return true if the item should be included and false if the
    // item should NOT be included
    filteredData = searchText.isEmpty ? data : data.filter({(dataString: String) -> Bool in
        // If dataItem matches the searchText, return true to include it
        return dataString.range(of: searchText, options: .caseInsensitive) != nil
    })

    tableView.reloadData()
}
}

这是运行时的样子。请注意,搜索结果显示在同一个表中,并且没有单独搜索界面的显示。

source: imgur.com

搜索集合视图的示例

由于UISearchBar非常简单,因此可以与任何abitrary视图结合使用来构建自己的搜索界面。以下是与集合视图配对的内容。

enter image description here

此代码与表视图的情况基本相同。

取消搜索并隐藏键盘

用户点击搜索栏后,会出现键盘,当您点按X时,您会注意到它不会消失。当用户点按搜索栏时,您可以显示取消按钮在取消时,隐藏键盘。

UISearchBarDelegate有一个漂亮的searchBarTextDidBeginEditing方法,当用户开始编辑搜索文本时会调用该方法。您可以在该方法中显示“取消”按钮:

func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
        self.searchBar.showsCancelButton = true
}

当用户点击取消按钮时,会调用委托的searchBarCancelButtonClicked方法。此时,您可以隐藏“取消”按钮,清除搜索栏中的现有文本并隐藏键盘,如下所示:

func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
        searchBar.showsCancelButton = false
        searchBar.text = ""
        searchBar.resignFirstResponder()
}

使用UISearchControllers(iOS 8 +)

管理搜索界面(仅适用于iOS 8及更高版本)的演示文稿的新方法是通过UISearchController。该控制器处理一些为您呈现单独搜索界面的逻辑和动画,同时仍允许您指定搜索结果的显示方式。

搜索表格的示例

UISearchController的Interface Builder对象库中当前没有内置对象。创建一个的最简单方法是以编程方式进行。这也会创建一个UISearchBar并将搜索控制器的searchBar属性设置为它。您可以以编程方式将此搜索栏添加到视图层次结构中。

为了更新您的搜索结果,您必须实施UISearchResultsUpdating协议并设置搜索控制器的searchResultsUpdater属性。

您不需要实现UISearchControllerDelegate,除非您需要挂钩搜索界面演示文稿周围的事件。

将所有代码放在一起代码如下所示。请注意,我们必须从updateSearchResultsForSearchController中的搜索栏中读取搜索文本。另外需要注意的是,我们将此视图控制器的definitionsPresentationContext属性设置为true。这意味着搜索控制器在呈现搜索界面时应使用此视图控制器的框架(与根视图控制器相对应)。在这种情况下,这意味着搜索界面将扩展到载体栏上方。

class ViewController: UIViewController, UITableViewDataSource, UISearchResultsUpdating {
    @IBOutlet weak var tableView: UITableView!

let data = ["New York, NY", "Los Angeles, CA", "Chicago, IL", "Houston, TX",
    "Philadelphia, PA", "Phoenix, AZ", "San Diego, CA", "San Antonio, TX",
    "Dallas, TX", "Detroit, MI", "San Jose, CA", "Indianapolis, IN",
    "Jacksonville, FL", "San Francisco, CA", "Columbus, OH", "Austin, TX",
    "Memphis, TN", "Baltimore, MD", "Charlotte, ND", "Fort Worth, TX"]

var filteredData: [String]!

var searchController: UISearchController!

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.dataSource = self
    filteredData = data

    // Initializing with searchResultsController set to nil means that
    // searchController will use this view controller to display the search results
    searchController = UISearchController(searchResultsController: nil)
    searchController.searchResultsUpdater = self

    // If we are using this same view controller to present the results
    // dimming it out wouldn't make sense. Should probably only set
    // this to yes if using another controller to display the search results.
    searchController.dimsBackgroundDuringPresentation = false

    searchController.searchBar.sizeToFit()
    tableView.tableHeaderView = searchController.searchBar

    // Sets this view controller as presenting view controller for the search interface
    definesPresentationContext = true
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("TableCell") as UITableViewCell
    cell.textLabel?.text = filteredData[indexPath.row]
    return cell
}

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return filteredData.count
}

func updateSearchResultsForSearchController(searchController: UISearchController) {
    if let searchText = searchController.searchBar.text {
        filteredData = searchText.isEmpty ? data : data.filter({(dataString: String) -> Bool in
            return dataString.rangeOfString(searchText, options: .CaseInsensitiveSearch) != nil
        })

        tableView.reloadData()
    }
}
}

这是运行时的样子。请注意,与搜索显示控制器示例不同,我们使用相同的表视图来显示搜索结果,而不是覆盖单独的表视图。但是,与仅使用搜索栏时不同,我们在转换到搜索界面时仍然拥有内置动画。

此外,当您使用此功能时,当用户免费点击取消按钮时,您将获得显示取消按钮并隐藏键盘的逻辑。

enter image description here

搜索集合视图的示例

我们可以轻松地使用搜索控制器来搜索集合视图。我们仍然提供搜索界面,但与使用搜索显示控制器时不同,我们不限于使用表格视图来显示搜索结果。

enter image description here

此代码与搜索上面的表格视图时的代码几乎相同。唯一值得注意的区别是我们必须在搜索栏的界面构建器中引入一个占位符视图,因为在搜索控制器的搜索栏中仍然存在一些怪癖,它们位于集合视图的补充视图中。

class ViewController: UIViewController, UICollectionViewDataSource, UISearchResultsUpdating {
    @IBOutlet weak var collectionView: UICollectionView!
    @IBOutlet weak var searchBarPlaceholder: UIView!
    ...
    override func viewDidLoad() {
        ...
        searchController.searchBar.sizeToFit()
        searchBarPlaceholder.addSubview(searchController.searchBar)
        automaticallyAdjustsScrollViewInsets = false
        definesPresentationContext = true
    }

    ...
}

导航视图中的搜索栏

常见的要求是将搜索栏放在导航栏中。

enter image description here

这可以在视图控制器的viewDidLoad中以编程方式配置,如下所示。

直接使用搜索栏时:

// create the search bar programatically since you won't be
// able to drag one onto the navigation bar
searchBar = UISearchBar()
searchBar.sizeToFit()

// the UIViewController comes with a navigationItem property
// this will automatically be initialized for you if when the
// view controller is added to a navigation controller's stack
// you just need to set the titleView to be the search bar
navigationItem.titleView = searchBar

使用搜索显示控制器:

searchDisplayController?.displaysSearchBarInNavigationBar = true

使用搜索控制器:

searchController.searchBar.sizeToFit()
navigationItem.titleView = searchController.searchBar

// By default the navigation bar hides when presenting the
// search interface.  Obviously we don't want this to happen if
// our search bar is inside the navigation bar.
searchController.hidesNavigationBarDuringPresentation = false

答案 1 :(得分:1)

我建议实现一个UISearchBar并将您的类添加为UISearchBar的委托,然后在委托方法中,您可以获取搜索栏文本并对数据进行搜索,然后相应地重新加载tableview数据

编辑:您可以使用本教程了解如何在UITableView上实现UISearchBar https://www.raywenderlich.com/472-uisearchcontroller-tutorial-getting-started