首页 > 解决方案 > 如何在函数中使用“映射”来过滤实体的不同属性?

问题描述

为了在 CoreData 应用程序中过滤搜索标记,我在实体数组上使用了“过滤器”和“地图”。在“过滤器”的情况下,我可以使用带有#keyPath 的 NSPredicate。对于“地图”,必须在代码内部定义属性。可以编写一个通用函数(而不是 searchNames、searchStreets、...),我可以在其中将实体和属性定义为参数?

class Person {
    @objc var name : String?
    @objc var city : String?
    @objc var street : String?
}

var personlist = [Person]()

func searchNames(_ searchText: String) -> [String?] {
    let predicate = NSPredicate(format: "%K BEGINSWITH[c] %@", #keyPath(Person.name), searchText)
    let names = personlist.filter({ predicate.evaluate(with: $0) }).map { $0.name }
    return names
}

func searchStreets(_ searchText: String) -> [String?] {
    let predicate = NSPredicate(format: "%K BEGINSWITH[c] %@", #keyPath(Person.street), searchText)
    let streets = personlist.filter({ predicate.evaluate(with: $0) }).map { $0.street }
    return streets
}

标签: swiftcore-data

解决方案


这有点棘手,因为您必须将 Swift 转换KeyPath为字符串,NSExpression但这是可能的

func searchProperty<V>(_ keyPath : KeyPath<Person,V>, searchText: String) -> [V] {
    let keyPathString = NSExpression(forKeyPath: keyPath).keyPath
    let predicate = NSPredicate(format: "%K BEGINSWITH[c] %@", keyPathString, searchText)
    return personlist.filter({ predicate.evaluate(with: $0) }).compactMap{$0[keyPath: keyPath]}
}

由于属性是可选comapctMap的,因此是更好的选择,因为它返回一个非可选数组。

你可以使用它

let result = searchProperty(\.name, searchText: "A")

考虑一个不继承自的类NSManageObject必须继承自NSObject并用dynamic

class Person : NSObject {
    @objc dynamic var name : String? ...

推荐阅读