Arrays 如何在Swift 3中搜索对象数组

Arrays 如何在Swift 3中搜索对象数组,arrays,swift,object,search,Arrays,Swift,Object,Search,我试图搜索从Firebase数据库中提取的对象数组。数据加载正常,但当我尝试搜索时,没有显示任何内容。我学习iOS/Swift开发才6周左右。下面是我的代码 我一点击搜索栏,应用程序就崩溃了。 我设法让搜索代码停止崩溃,但我在搜索中没有得到任何回报。这是因为我正在搜索Firebase数据库吗?我正在将firebase数据加载到一个数组中,所以它应该是可搜索的,对吗 import UIKit import Firebase class ServicesTableViewController: U

我试图搜索从Firebase数据库中提取的对象数组。数据加载正常,但当我尝试搜索时,没有显示任何内容。我学习iOS/Swift开发才6周左右。下面是我的代码

我一点击搜索栏,应用程序就崩溃了。
我设法让搜索代码停止崩溃,但我在搜索中没有得到任何回报。这是因为我正在搜索Firebase数据库吗?我正在将firebase数据加载到一个数组中,所以它应该是可搜索的,对吗

import UIKit
import Firebase

class ServicesTableViewController: UITableViewController, UISearchResultsUpdating {

    var services = [Service]()
    var filteredSearch = [Service]()

    var searchController: UISearchController!
    var resultsController = UITableViewController()


    override func viewDidLoad() {
        super.viewDidLoad()


        // Turn this back on to cache data
        FIRDatabase.database().persistenceEnabled = true

        fetchServices()

        self.resultsController.tableView.dataSource = self
        self.resultsController.tableView.delegate = self

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

        searchController.dimsBackgroundDuringPresentation = false
        searchController.searchBar.placeholder = "Search services..."
        searchController.searchBar.tintColor = UIColor.white
        searchController.searchBar.barTintColor = UIColor(red: 164.0/255.0, green: 45.0/255.0, blue: 9.0/255.0, alpha: 1.0)

        navigationItem.backBarButtonItem = UIBarButtonItem(title: " ", style: .plain, target: nil, action: nil)
    }

    // MARK: - Search Controller

    func filterContent(for searchText: String) {
        filteredSearch = services.filter({ (service) -> Bool in
            if let name = service.name {
                let isMatch = name.localizedCaseInsensitiveContains(searchText)
                return isMatch
            }

            return false
        })
    }

    func updateSearchResults(for searchController: UISearchController) {
        if let searchText = searchController.searchBar.text {
            filterContent(for: searchText)
            tableView.reloadData()
        }
    }

    // MARK: Database connection and data fetch

    func fetchServices () {

        FIRDatabase.database().reference().child("services").observe(.childAdded, with: { (snapshot) in

            print(snapshot)

            if let dictionary = snapshot.value as? [String: AnyObject] {

                let service = Service()
                service.setValuesForKeys(dictionary)

                self.services.append(service)


                self.tableView.reloadData()



            }

        })


    }



    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {

        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if searchController.isActive {
            return filteredSearch.count
        } else {
            return services.count
        }
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cellIdentifier = "Cell"
        let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! ServicesTableViewCell


        // Check to see if the user is searching or not
        let service = (searchController.isActive) ? filteredSearch[indexPath.row] : services[indexPath.row]

//        let service = services[indexPath.row]
        cell.programLabel.text = service.name
        cell.programLabel.font = UIFont(name: "Avenir-Medium", size: 18.0)
        cell.programLabel.textColor = UIColor(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 1.0)
        cell.branchLabel.text = service.branch
        cell.branchLabel.font = UIFont(name: "Avenir-Medium", size: 14.0)
        cell.branchLabel.textColor = UIColor(red: 90.0/255.0, green: 86.0/255.0, blue: 92.0/255.0, alpha: 1.0)
        cell.servicesLabel.text = service.shortDesc
        cell.servicesLabel.font = UIFont(name: "Avenir-Light", size: 14.0)
        cell.servicesLabel.textColor = UIColor(red: 164.0/255.0, green: 45.0/255.0, blue: 9.0/255.0, alpha: 1.0)
        cell.thumbnailImageView.image = UIImage(named: service.imageName!)


        return cell
    }


    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "showServicesDetail" {
            if let indexPath = tableView.indexPathForSelectedRow {
                let destinationController = segue.destination as! ServicesDetailViewController
                destinationController.services = services[indexPath.row]
            }
        }
    }





}
这是我目前的故事板。只有两个视图和一个导航控制器,

我假设您要按名称搜索:

filteredSearch = services.filter { (service: Service) -> Bool in

    if let name = service.name,
        let searchText = self.searchController.searchBar.text?.lowercased() {
        return name.lowercased().contains(searchText)
    } else {
        return false
    }
}
另外,让我们将
filteredSearch
更改为
服务的数组

var filteredSearch = [Service]()

如果您的
服务
类别如下

class Service: NSObject {
    var serviceID: NSInteger!
    var serviceName: String!

}
您可以使用包含self.searchController.searchBar.text的
serviceName
检索筛选器服务

let fiterServices = services.filter({$0.serviceName.lowercased().range(of: self.searchController.searchBar.text!.lowercased()) != nil})
希望这有帮助。

我有一个对象数组(codeDataObjectList)

下面的代码可以搜索每个对象中的文本,您可以使用
filteredTableData

func  updateSearchResults(for searchController: UISearchController) {
        filteredTableData.removeAll(keepingCapacity: false)
        let searchPredicate = NSPredicate(format: "code CONTAINS[c] %@ OR longDescription CONTAINS[c] %@ OR shortDescription CONTAINS[c] %@", searchController.searchBar.text!, searchController.searchBar.text!, searchController.searchBar.text!)
        let array = (self.codeDataObjectList as NSArray).filtered(using: searchPredicate)
        filteredTableData = array as! [CodeDataObject]
        self.tableView.reloadData()
    }

因为
services.filter
将返回
Service
的数组,但
filteredSearch
字符串的数组。为什么不
var filteredSearch=[Service]()
?您需要向我们展示您的
服务
课程非常感谢您的建议。我对var filteredSearch=[Service]()进行了更改,但是我遇到了一个错误,无法将(string)->Bool的值转换为预期的参数类型(Service)->Bool。这是我创建的类。文件名“Service.swift”导入UIKit类服务:NSObject{var name:String?var branch:String?var shortDesc:String?var longDesc:String?var imageName:String?var mainPhone:String?var位置:String?var小时数:String?var网站:String?}我正在使用此链接中的教程。在我完成定制课程之前,我一直工作得很好。谢谢,丹。我尝试了你的代码,它构建得很好,没有错误,但当我点击搜索程序进行搜索时,应用程序因SIGABRT错误而崩溃(Danh,这是控制台的错误。2017-04-03 19:59 MCCSServicesGuide[64700:9332471]***在[UITableView dequeueReusableCellWithIdentifier:forIndexPath:]、/BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3600.7.47/UITableView.m:6730 2017-04-03 19:59:19.336 MCCSServicesGuide[64700:9332471]中的断言失败***由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“无法将具有标识符单元格的单元格出列-必须为标识符注册nib或类,或在情节提要中连接原型单元格”***第一次抛出调用堆栈:我想tableView找不到“单元格”标识符。如果可能的话,让我看看你的故事板和代码。我刚刚编辑了我的帖子,并将tableviewcontroller中的所有当前代码加上自定义类。你是否忘记了为故事板中的
ServiceStablevewCell
单元格设置
identifier
?在Main.storyboard中选择你的单元格,然后选择Att右侧的ributes inspector,并在
标识符
框中设置
单元格
。谢谢你,Sree。当我尝试你的代码时,我得到了一个错误“行上的连续状态必须用分隔符分隔”;我可能做了一些我想做的事情sure@ShootLighter:我进行了编辑。请查看代码(删除了nil旁边的右括号和$0.serviceName之间的空格)@ShootLighter如果解决了您的问题,请接受答案。我喜欢这个解决方案,因为它使我能够搜索多个字段,但我在理解如何在代码中实现它时遇到一些困难。抱歉,我确定是我,因为我是新来的。我刚刚发布了tableviewcontroller的所有代码。如果您不介意,我将如何实现这段代码使用了我的数组、变量和类。?如果这不合理,很抱歉,谢谢大家的帮助。我设法让搜索代码停止崩溃,但我在搜索中没有得到任何回报。这是因为我在搜索Firebase数据库吗?我正在将Firebase数据加载到一个数组中,因此它应该可以搜索,对吗?这就是为什么您推荐使用NSPredicate?提前感谢您的帮助。对不起,我不知道
func  updateSearchResults(for searchController: UISearchController) {
        filteredTableData.removeAll(keepingCapacity: false)
        let searchPredicate = NSPredicate(format: "code CONTAINS[c] %@ OR longDescription CONTAINS[c] %@ OR shortDescription CONTAINS[c] %@", searchController.searchBar.text!, searchController.searchBar.text!, searchController.searchBar.text!)
        let array = (self.codeDataObjectList as NSArray).filtered(using: searchPredicate)
        filteredTableData = array as! [CodeDataObject]
        self.tableView.reloadData()
    }