swift - 如何在函数中使用“映射”来过滤实体的不同属性?
问题描述
为了在 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
}
解决方案
这有点棘手,因为您必须将 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? ...
推荐阅读
- github - 在 Heroku 上使用 .gitignore
- android - 创建类 viewModel 的实例时出错
- mongodb - 您可以在 mongodb 中自动创建空间索引吗?
- python - Python - Tkinter 事件生成
- sharepoint-online - Sharepoint Online 中的工作流程
- javascript - jQuery中的Addclass函数不添加类
- java - Ognl 表达式在选择标记的“列表”属性中不起作用,而在“名称”属性中工作正常
- ups - UPS 货件 JSON 文档
- c# - 将 XML 反序列化为 for 循环中的 C# 对象列表太慢
- mysql - 计算来自两个不同表的记录数并将它们分组