在Swift中以编程方式向表格视图添加搜索栏

6
我有一个textfield,它的输入视图是一个tableview。我想在这个tableview上添加两个东西。
1)添加搜索栏。
2)在tableview顶部添加取消按钮。
class enterYourDealVC: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UISearchDisplayDelegate, UISearchResultsUpdating {
var tableView: UITableView  =   UITableView()
let searchController = UISearchController(searchResultsController: nil)

var dealAirports = [
    airPorts(name: "Airport1", shortcut: "AP1")!),
    airPorts(name: "Airport2", shortcut: "AP2")!)
]
var filteredAirports = [airPorts]()


//view did load
    tableView = UITableView(frame: UIScreen.mainScreen().bounds, style: UITableViewStyle.Plain)
    tableView.delegate      =   self
    tableView.dataSource    =   self
    tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")

    searchController.searchResultsUpdater = self
    searchController.dimsBackgroundDuringPresentation = false
    definesPresentationContext = true
    tableView.tableHeaderView = searchController.searchBar
    toTextField.inputView = self.tableView

//here is my search function
func filterContentForSearchText(searchText: String, scope: String = "All") {
    filteredAirports = dealAirports.filter { ap in
        return ap.name.lowercaseString.containsString(searchText.lowercaseString)
    }

    tableView.reloadData()
}
}

这段代码存在问题,它无法进行搜索。当我点击搜索栏时,它会关闭表格视图并将我带回到 viewcontroller。我该如何解决这个问题?

并且我该如何为这个表格视图添加取消按钮?


UISearchController Apple示例代码: Apple示例代码。 这将有助于您实现。 - Chandan
如果我懂Objective-C的话会很有帮助,但是它看起来对我来说非常复杂。我会继续研究这段代码。 - Berk Kaya
示例代码在 Xcode 10 下无法正常打开运行。 - John Doe
@jsloop 是的,这个问题是3年前提出的。这可能是原因。 - Berk Kaya
5个回答

20

这将添加一个搜索栏

lazy var searchBar:UISearchBar = UISearchBar()

override func viewDidLoad()
{
     searchBar.searchBarStyle = UISearchBar.Style.default
    searchBar.placeholder = " Search..."
    searchBar.sizeToFit()
    searchBar.isTranslucent = false
    searchBar.backgroundImage = UIImage()
    searchBar.delegate = self
    navigationItem.titleView = searchBar

}

func searchBar(_ searchBar: UISearchBar, textDidChange textSearched: String)
{
    ...your code...
}

navigationItem.titleView非常出色。它保持粘性,非常适合某些用途。谢谢! - Dan Rosenstark

7
在 Swift 4.1 和 Xcode 9.4.1 中, 步骤1 将 UISearchBarDelegate 添加到您的视图控制器。 步骤2
//Write this code in viewDidLoad() or your required function
let searchBar:UISearchBar = UISearchBar()
//IF you want frame replace first line and comment "searchBar.sizeToFit()"
//let searchBar:UISearchBar = UISearchBar(frame: CGRect(x: 10, y: 10, width: headerView.frame.width-20, height: headerView.frame.height-20))
searchBar.searchBarStyle = UISearchBarStyle.prominent
searchBar.placeholder = " Search..."
searchBar.sizeToFit()
searchBar.isTranslucent = false
searchBar.backgroundImage = UIImage()
searchBar.delegate = self
yourViewName.addSubview(searchBar)//Here change your view name

第三步

func searchBar(_ searchBar: UISearchBar, textDidChange textSearched: String) {
    //your code here....
}

1

//首先编写搜索“UISearchBarDelegate”的委托 //MARK:- 搜索按钮操作

@IBAction func searchWithAddress(_ sender: Any) {
let searchController = UISearchController(searchResultsController: nil)
searchController.searchBar.delegate = self
self.present(searchController, animated: true, completion: nil)
}

1
这是一段用Swift编写的代码片段,与内容相关。若需了解更多,请参考评论中提到的苹果文档。
注意:IOS8.0已经弃用UISearchDisplayController,建议使用UISearchController。
希望这能对你有所帮助。
“ContactTVC”
class ContactTVC:UITableViewController{   
// MARK: Types
/// State restoration values.
enum RestorationKeys : String {
    case viewControllerTitle
    case searchControllerIsActive
    case searchBarText
    case searchBarIsFirstResponder
}

struct SearchControllerRestorableState {
    var wasActive = false
    var wasFirstResponder = false
}


/*
 The following 2 properties are set in viewDidLoad(),
 They an implicitly unwrapped optional because they are used in many other places throughout this view controller
 */

/// Search controller to help us with filtering.
var searchController: UISearchController!

/// Secondary search results table view.
var resultsTableController: ResultsTableController!

/// Restoration state for UISearchController
var restoredState = SearchControllerRestorableState()
var arrayContacts: Array<CNContact> = []
var searchResultArrayContacts: Array<CNContact> = []

override func viewDidLoad() {
    super.viewDidLoad()

    resultsTableController = ResultsTableController()
// We want to be the delegate for our filtered table so didSelectRowAtIndexPath(_:) is called for both tables.
    resultsTableController.tableView.delegate = self

    searchController = UISearchController(searchResultsController: resultsTableController)

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

    searchController.delegate = self
    searchController.dimsBackgroundDuringPresentation = false // default is YES
    searchController.searchBar.delegate = self    // so we can monitor text changes + others

  /*
     Search is now just presenting a view controller. As such, normal view controller
     presentation semantics apply. Namely that presentation will walk up the view controller
     hierarchy until it finds the root view controller or one that defines a presentation context.
     */

    definesPresentationContext = true

}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    // Restore the searchController's active state.
    if restoredState.wasActive {
        searchController.active = restoredState.wasActive
        restoredState.wasActive = false

        if restoredState.wasFirstResponder {
            searchController.searchBar.becomeFirstResponder()
            restoredState.wasFirstResponder = false
        }
    }
}

//MARK override TableViewDelegates/Datasource methods  
}
extension ContactTVC: UISearchResultsUpdating{

// MARK: UISearchResultsUpdating

func updateSearchResultsForSearchController(searchController: UISearchController) {

        if let text = searchController.searchBar.text where (text.isEmpty == false){
        {

                            // Hand over the filtered results to our search results table.

                            let resultsController = searchController.searchResultsController as! ResultsTableController

                            resultsController.filteredProducts = Array(searchResult)

                            resultsController.tableView.reloadData()

                        dispatch_async(dispatch_get_main_queue(), {
                            self.tableViewContacts.reloadData()
                        })

                }   
         }
}
}
//MARK: SearchBarDelegate
extension ContactTVC: UISearchBarDelegate{

func searchBar(searchBar: UISearchBar, textDidChange searchText: String) {

    if let text = searchBar.text where (text.isEmpty == false) {

          // update the search result array by filtering….


                if searchResult.count > 0{

                    self.searchResultArrayContacts = Array(searchResult)
                }
                else{

                    self.searchResultArrayContacts = Array(self.arrayContacts)
                }

                dispatch_async(dispatch_get_main_queue(), {
                    self.tableViewContacts.reloadData()
                })
     }
}


func searchBarCancelButtonClicked(searchBar: UISearchBar) {

    searchBar.text = nil
    searchBar.resignFirstResponder()

}
}

/// 这个表视图控制器负责在用户在搜索字段中输入时显示筛选后的产品。
class ResultsTableController: UITableViewController {
// MARK: Properties

let reusableIdentifier = "contactCell"

var filteredProducts = [CNContact]()

override func viewDidLoad() {

    self.tableView.emptyDataSetSource = self
    self.tableView.emptyDataSetDelegate = self

}


// MARK: UITableViewDataSource
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

    return filteredProducts.count
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell =  UITableViewCell(style: .Subtitle, reuseIdentifier: reusableIdentifier)

     var contact = CNContact()
     contact = filteredProducts[indexPath.row]

    // Configure the cell...
    cell.textLabel?.text = contact.givenName

    let phones = contact.phoneNumbers[0].value as! CNPhoneNumber

    cell.detailTextLabel?.text = phones.stringValue

    return cell
}
}

谢谢


1

Swift 4+

class SearchViewController: UIViewController {

    @IBOutlet weak var maintableView: UITableView!
    @IBOutlet weak var searchUIBar: UISearchBar!
        
    var isSearch : Bool = false
    var tableData = ["Afghanistan", "Algeria", "Bahrain","Brazil", "Cuba", "Denmark","Denmark", "Georgia", "Hong Kong", "Iceland", "India", "Japan", "Kuwait", "Nepal"];
    var filteredTableData:[String] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        maintableView.dataSource = self
        maintableView.delegate = self
        searchUIBar.delegate = self
        maintableView.reloadData()

    }
}

extension SearchViewController: UISearchBarDelegate{
    //MARK: UISearchbar delegate
    func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
           isSearch = true
    }
       
    func searchBarTextDidEndEditing(_ searchBar: UISearchBar) {
           searchBar.resignFirstResponder()
           isSearch = false
    }
       
    func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
           searchBar.resignFirstResponder()
           isSearch = false
    }
       
    func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
           searchBar.resignFirstResponder()
           isSearch = false
    }
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
        if searchText.count == 0 {
            isSearch = false
            self.maintableView.reloadData()
        } else {
            filteredTableData = tableData.filter({ (text) -> Bool in
                let tmp: NSString = text as NSString
                let range = tmp.range(of: searchText, options: NSString.CompareOptions.caseInsensitive)
                return range.location != NSNotFound
            })
            if(filteredTableData.count == 0){
                isSearch = false
            } else {
                isSearch = true
            }
            self.maintableView.reloadData()
        }
    }

}

extension SearchViewController: UITableViewDelegate{
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = maintableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        if (isSearch) {
            cell.textLabel?.text = filteredTableData[indexPath.row]
            return cell
        }
        else {
            cell.textLabel?.text = tableData[indexPath.row]
            print(tableData[indexPath.row])
            return cell
        }
    }

    }

    extension SearchViewController: UITableViewDataSource{
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
         if(isSearch) {
             return filteredTableData.count
         }else{
            return tableData.count
        }
         
    }
}

虽然这段代码可能回答了问题,但提供关于它如何及/或为什么解决问题的更多背景信息会增强答案的长期价值。 - Tomer Shetah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接