如何使用 NSPredicate 在对象中搜索?

How to search in an Object with NSPredicate?

在 Nsarray 中,我需要过滤所有包含 searchKey(例如 39013)的元素。目前,它返回错误的值。我的搜索功能有什么问题?我认为问题出在 FORMAT 行,但不知道该怎么办?

要求: Searchbar 必须搜索 LocationModel 对象中声明的 DesenNo 中的值。

这是对象

import UIKit

class LocationModel: NSObject {
    //properties
    var DesenNo: String?
    var Dolar: String?
    var Zemin: String?
    var En: String?
    var Euro: String?
    var Renk: String?
}

这是我的搜索功能:

func updateSearchResults(for searchController: UISearchController) {
    if searchController.isActive {
        filteredData.removeAll(keepingCapacity: false)
        let searchPredicate = NSPredicate(format: "LocationModel.DesenNo CONTAINS[c] %@", searchController.searchBar.text!)

        let array = self.feedItems.filter { searchPredicate.evaluate(with: ([=11=] as! LocationModel).DesenNo) }

        let filterArray = array.map {([=11=] as! LocationModel).DesenNo}
        filteredData = filterArray as! [String]
        listTableView.reloadData()
    } else {
        filteredData.removeAll(keepingCapacity: false)
        listTableView.reloadData()
    }
}

您不需要谓词。只需使用一个简单的 Swift 数组过滤器:

假设self.feedItems声明为[LocationModel],你只需要:

let matchingModels = self.feedItems.filter { [=10=].DesenNo?.contains(searchController.searchBar.text!) }

如果您希望将这些结果缩减为仅包含相应 DesenNo 值的列表,请执行:

filteredData = matchingModels.map { [=11=].DesenNo }

附带说明一下,您的 LocationModel class 不需要扩展 NSObject。它也应该是 struct,而不是 class

另请注意,标准做法是变量和方法名称以小写字母开头。 Class 和结构名称以大写开头。

func updateSearchResults(for searchController: UISearchController) {
    if searchController.isActive {    
        let matchingModels = self.feedItems.filter { [=12=].DesenNo?.contains(searchController.searchBar.text!) }
        filteredData = matchingModels.map { [=12=].DesenNo }

        listTableView.reloadData()
    } else {
        filteredData.removeAll(keepingCapacity: false)

        listTableView.reloadData()
    }
}

如果您出于某种原因真的想使用 NSPredicate,您可以将代码更新为:

func updateSearchResults(for searchController: UISearchController) {
    if searchController.isActive {
        let searchPredicate = NSPredicate(format: "DesenNo CONTAINS[c] %@", searchController.searchBar.text!)

        let array = self.feedItems.filter { searchPredicate.evaluate(with: [=13=]) }
        filteredData = array.map { [=13=].DesenNo }

        listTableView.reloadData()
    } else {
        filteredData.removeAll(keepingCapacity: false)
        listTableView.reloadData()
    }
}

如果 self.feedItems 实际上是 NSArray 而不是适当的 Swift 数组,请更改:

... = self.feedItems.filter { ...

至:

... = (self.feedItems as! [LocationModel]).filter { ...