使用NSSortDescriptor的Core Data实体中String属性的最大长度

问题描述 投票:0回答:1

我想找到一个实体属性最多的单词。我正在尝试创建排序描述符以比较字符串长度。代码可以编译,但是执行提取查询时出现错误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
    }
}

错误的屏幕截图:enter image description here

编辑:我调整/更正了选择符说明符的签名,但这也失败了:#selector(NSString.comparatorOfStringLengths(_:)))

swift core-data nssortdescriptor
1个回答
1
投票

我可能对此有误,但我认为使用Core Data(iOS 13)仍然无法实现NSPredicateNSSortDescriptor这样的功能。

[一个选项可能是添加一个数字类型的附加属性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使抓取速度更快:

enter image description here

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技能很差,欢迎改正。)

© www.soinside.com 2019 - 2024. All rights reserved.