【问题标题】:How to Search an array of object in Swift 3如何在 Swift 3 中搜索对象数组
【发布时间】:2017-08-27 21:40:00
【问题描述】:

我正在尝试搜索从 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]
            }
        }
    }





}

这是我当前的故事板。只有两个视图和一个导航控制器, enter image description here

【问题讨论】:

  • 因为services.filter 将返回Service 的数组,但filteredSearch 是String 的数组。为什么不var filteredSearch = [Service]()?
  • 您需要向我们展示您的Service 班级
  • 非常感谢您的建议。我对 var filteredSearch = [Service]() 进行了更改,但出现错误无法将(字符串)-> Bool 的值转换为预期的参数类型(服务)-> Bool。
  • 这是我制作的课程。文件名 "Service.swift" 导入 UIKit 类 Service: NSObject { var name: String? var 分支:字符串? var shortDesc:字符串? var longDesc:字符串? var imageName:字符串? var mainPhone:字符串? var 位置:字符串? var hours:字符串? var 网站:字符串? }
  • 我正在使用此链接中的教程。在我制作自定义课程之前工作得很好。 youtube.com/watch?v=XtiamBbL5QU

标签: arrays swift object search


【解决方案1】:

如果你的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})

希望这会有所帮助。

【讨论】:

  • 谢谢你。当我尝试您的代码时,出现错误“一行上的连续状态必须用 ; 分隔”我可能做了我确定的事情
  • @ShootLighter:我进行了编辑。请查看代码(删除了 nil 旁边的右括号和 $0.serviceName 之间的空格)
  • @ShootLighter 如果解决了您的问题,请接受答案。
【解决方案2】:

我假设您想按名称搜索:

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 更改为Service 的数组:

var filteredSearch = [Service]()

【讨论】:

  • 谢谢丹。我试过你的代码,它构建得很好,没有错误,但是当我点击搜索器搜索应用程序时,应用程序因 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 或类或连接情节提要中的原型单元 *** First throw call stack:
  • 我认为 tableView 找不到要出列的“Cell”标识符。如果可能的话,让我看看你的故事板和代码
  • 我刚刚编辑了我的帖子,并将 tableviewcontroller 中的所有当前代码加上自定义类。
  • 您是否忘记为情节提要中的ServicesTableViewCell 单元格设置identifier? 在 Main.storyboard 中选择您的单元格,然后在右侧选择属性检查器并在 Indentifier 框中设置 Cell。
【解决方案3】:

我有一个对象数组(codeDataObjectList)

    import Foundation

    class CodeDataObject:NSObject{

        private var collections:[String]?
        private var code: String?
        private var shortDescription: String?
        private var longDescription: String?
        private var sectionName: String?
        private var specialtyName: String?
        private var chapterName: String?
        private var isStarred: Bool?
        private var starredListIndex:Int?
        private var type: String?
        .
        .
        .

下面的代码可以搜索每个对象中的文本,您可以使用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()
    }

【讨论】:

  • 我喜欢 Hamed 这个解决方案,因为它使我能够搜索多个字段,但我在理解如何在我的代码中实现它时遇到了一些困难。对不起,我确定是我,因为我是新人。我刚刚发布了 tableviewcontroller 的所有代码。如果您不介意,我将如何使用我的数组、变量和类来实现此代码。 ?对不起,如果这没有意义,谢谢大家帮助我。
  • 我设法让搜索代码停止崩溃,但我的搜索没有任何回报。这是因为我正在搜索 Firebase 数据库吗?我正在将 firebase 数据加载到一个数组中,所以它应该是可搜索的,对吗?这就是你推荐使用 NSPredicate 的原因吗?提前感谢您的帮助。
  • 对不起,我不知道
猜你喜欢
  • 1970-01-01
  • 2015-02-26
  • 1970-01-01
  • 2012-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多