我想找到一个实体属性最多的单词。我正在尝试创建排序描述符以比较字符串长度。代码可以编译,但是执行提取查询时出现错误unsupported NSSortDescriptor selector: comparatorOfStringLengths
。我尝试了NSSortDescriptor
的比较器块版本,但不受支持。
query.sortDescriptors = [
NSSortDescriptor.init(key: "word", ascending: false, selector: #selector(NSString.comparatorOfStringLengths))
]
下面是比较器方法签名的最新版本。我还尝试使用带有两个参数的static
函数,并且也使用Any
而不是String
,得到相同的结果。我将此签名建模为func localizedStandardCompare(_ string: String) -> ComparisonResult
标准功能。
extension NSString {
@objc func comparatorOfStringLengths(_ b: String) -> ComparisonResult {
if self.length < b.length {
return .orderedAscending
}
if self.length > b.length {
return .orderedDescending
}
return .orderedSame
}
}
编辑:我调整/更正了选择符说明符的签名,但这也失败了:#selector(NSString.comparatorOfStringLengths(_:)))
我可能对此有误,但我认为使用Core Data(iOS 13)仍然无法实现NSPredicate
和NSSortDescriptor
这样的功能。
[一个选项可能是添加一个数字类型的附加属性wordlen
,该属性保留word
的长度。并获取wordlen
的最大值的实体。
为了进一步说明,我迅速使用实体Person
切换到我的Person标准示例,该实体具有字符串属性name
(对应于OP中的word
)和整数属性namelen
。
使用新功能validateNamelen
,它将放置在生成Person
代码的位置:
extension Person {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Person> {
return NSFetchRequest<Person>(entityName: "Person")
}
@NSManaged public var name: String?
@NSManaged public var namelen: NSNumber?
@objc func validateNamelen(_ ioValue: AutoreleasingUnsafeMutablePointer<AnyObject?>) throws {
ioValue.pointee = NSNumber.init(integerLiteral: name!.count)
}
}
将由Core Data触发,并有助于将namelen
的值与新创建或更新的Person
实体进行同步。
然后在NameLenIndex
上添加索引namelen
使抓取速度更快:
Swift 5评估代码:
// Create Persons
var personObj: Person = Person(context: mainContext)
personObj.name = "Person1 A"
personObj = Person(context: mainContext)
personObj.name = "Person2 BB"
personObj = Person(context: mainContext)
personObj.name = "Person3 CCC"
personObj = Person(context: mainContext)
personObj.name = "Person4 A"
personObj = Person(context: mainContext)
personObj.name = "Person5 BB"
personObj = Person(context: mainContext)
personObj.name = "Person6 CCC"
saveContext()
// Get person
let request: NSFetchRequest<Person> = Person.fetchRequest()
// Which persons?
let predicateMax = NSPredicate(format: "namelen==max(namelen)")
let predicateMin = NSPredicate(format: "namelen==min(namelen)")
// Persons with longest names
request.predicate = predicateMin;
print("Persons with shortes Names:")
do {
let results = try mainContext.fetch(request)
for result in results {
print(result.name ?? "No name found")
}
} catch {
print("Error: \(error)")
}
request.predicate = predicateMax;
print("Persons with longest Names:")
do {
let results = try mainContext.fetch(request)
for result in results {
print(result.name ?? "No name found")
}
} catch {
print("Error: \(error)")
}
在开始时给出一个空的数据库,输出是这样的:
Persons with shortes Names:
Person1 A
Person4 A
Persons with longest Names:
Person6 CCC
Person3 CCC
((我的Swift 5技能很差,欢迎改正。)