繁体   English   中英

如何使用Swift创建UISearchBar以搜索Tableview数据的选项?

[英]How to create UISearchBar to search option for my Tableview data using Swift?

就我而言,我正在尝试为我的tableview数据实现search功能。 在这里,我将JSON数据加载到Tableview sectionrows 在自定义cell我正在显示名称,我想按名称创建搜索。 我尝试了下面的代码,但结果没有任何显示。 如何以适当的方式进行搜索功能。

var sections = [Section]()
var filteredNames = [Section]()
var searchController : UISearchController!

Tableview代表

// MARK: UITableview Delegates

    func numberOfSections(in tableView: UITableView) -> Int {
        return sections.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if isFiltering {
            return filteredNames[section].result.count
        } else {
            return sections[section].result.count
        }
    }

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sections[section].title
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell:MyCustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! MyCustomCell
        let item = sections[indexPath.section].result[indexPath.row]
        let filteritem = filteredNames[indexPath.section].result[indexPath.row]
        if isFiltering {
            cell.nameLabel.text = filteritem.name
        } else {
            cell.nameLabel.text = item.name
        }
        return cell
    }

SearchBarAction和代理

 // MARK: UISearchBar Delegates

@IBAction func searchAction(_ sender: Any) {

    searchController = UISearchController(searchResultsController: nil)
    searchController.hidesNavigationBarDuringPresentation = false
    searchController.searchBar.keyboardType = UIKeyboardType.asciiCapable
    searchController.searchBar.barTintColor = #colorLiteral(red: 0.317096545, green: 0.5791940689, blue: 0.3803742655, alpha: 1)
    searchController.searchBar.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
    searchController.dimsBackgroundDuringPresentation = false

    // Make this class the delegate and present the search
    self.searchController.searchBar.delegate = self
    searchController.searchResultsUpdater = self
    present(searchController, animated: true, completion: nil)
}

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    guard let searchText = searchBar.text else {
        isFiltering = false
        return
    }
    filteredNames = sections[indexPath.section].result[indexPath.row].filter({
        return $0.lowercased().contains(searchText.lowercased())
    })
    isFiltering = filteredNames.count > 0
    self.tableView.reloadData()
}

错误:出现错误-使用未解析的标识符'indexPath'; 您是说'IndexPath'吗?

我在这里进行一些计算上的猜测,您可能需要自己进行一些修改。

在我的示例中(上面评论中提供的链接),我只是过滤名称数组。 如果您要过滤各节中的项目,然后删除所有空节,则如果您有多个节则更加困难。

因此,您的filter方法应该看起来像这样:

guard let searchText = searchBar.text else {
    isFiltering = false
    return
}

self.filteredNames = sections.map({ 
    let filteredResult = $0.result.filter { $0.name.contains(searchText) }
    $0.result = filteredResult
    return $0
)).filter { !$0.result.isEmpty } 

因此,这里您遍历每个部分,然后过滤结果数组以查找搜索字符串中的匹配项,然后删除结果为0的所有部分。

请注意,您可能可以缩短

self.filteredNames = sections.map({ 
    $0.result = $0.result.filter { $0.name.contains(searchText) }
)).filter { !$0.result.isEmpty } 

编辑:

import UIKit
import PlaygroundSupport
import UIKit
import PlaygroundSupport

struct Section {
    let title: String
    var result: [String]
}

class ViewController: UITableViewController {

    let searchController = UISearchController(searchResultsController: nil)

    let names = [
        Section(title: "J", result: [
            "John",
            "Jason"
        ]),
        Section(title: "M", result: [
            "Martin",
            "Michael",
            "Mattew"
        ]),
        Section(title: "T", result: [
            "Terry",
            "Thomas"
        ]),
        Section(title: "S", result: ["Steven"])
    ]
    var filteredNames = [Section]()

    override func viewDidLoad() {
        super.viewDidLoad()

        self.title = "Search Example"

        searchController.searchResultsUpdater = self
        searchController.obscuresBackgroundDuringPresentation = false
        searchController.searchBar.placeholder = "Search"
        navigationItem.searchController = searchController
        definesPresentationContext = true
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        if isFiltering() {
            return filteredNames.count
        } else {
            return names.count
        }
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if isFiltering() {
            return filteredNames[section].result.count
        } else {
            return names[section].result.count
        }
    }

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        if isFiltering() {
            return filteredNames[section].title
        } else {
            return names[section].title
        }
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = UITableViewCell() // don't do this, i am for example.

        var name: String
        if isFiltering() {
            name = filteredNames[indexPath.section].result[indexPath.row]
        } else {
            name = names[indexPath.section].result[indexPath.row]
        }

        cell.textLabel?.text = name
        return cell
    }

    func searchBarIsEmpty() -> Bool {
        // Returns true if the text is empty or nil
        return searchController.searchBar.text?.isEmpty ?? true
    }

    func isFiltering() -> Bool {
        return searchController.isActive && !searchBarIsEmpty()
    }

    func filterContentForSearchText(_ searchText: String, scope: String = "All") {

        filteredNames = names.map({
            let result = $0.result.filter {
                $0.localizedLowercase.contains(searchText.lowercased())
            }
            return Section(title: $0.title, result: result)
        }).filter { !$0.result.isEmpty }

        tableView.reloadData()
    }
}

extension ViewController: UISearchResultsUpdating {
    func updateSearchResults(for searchController: UISearchController) {
        filterContentForSearchText(searchController.searchBar.text!)
    }
}

let vc = ViewController()
let nav = UINavigationController()
nav.viewControllers = [vc]

PlaygroundPage.current.liveView = nav

首先,您正在过滤部分,因此将数组命名为

var filteredSections = [Section]()

filteredNames具有误导性,并暗示该数组为[String]

一种可能的解决方案是使用过滤后的内容创建新部分

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    if !searchText.isEmpty {
        filteredSections = sections.compactMap { section -> Section? in
            let filteredContent = section.result.filter {$0.name.range(of: searchText, options: .caseInsensitive) != nil }
            return filteredContent.isEmpty ? nil : Section(title: section.title, result: filteredContent)
        }
        isFiltering = true  
    } else {  
        filteredSections.removeAll()
        isFiltering = false
    }
    self.tableView.reloadData()
}

并且表视图数据源的方法必须更改为

func numberOfSections(in tableView: UITableView) -> Int {
    return isFiltering ? filteredSections.count : sections.count
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let currentSection = isFiltering ? filteredSections[section] : sections[section]
    return currentSection.result.count
}

func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return isFiltering ? filteredSections[section].title : sections[section].title
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier, for: indexPath) as! MyCustomCell
    let section = isFiltering ? filteredSections[indexPath.section] : sections[indexPath.section]
    let item = section.result[indexPath.row]
    cell.nameLabel.text = item.name
    return cell
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM