【问题标题】:Maximum length of String attribute in Core Data entity using NSSortDescriptor使用 NSSortDescriptor 的核心数据实体中字符串属性的最大长度
【发布时间】:2020-04-29 22:55:23
【问题描述】:

我想找到实体属性中字符数最多的单词。我正在尝试创建一个排序描述符来比较字符串长度。代码可以编译,但是在执行 fetch 查询时出现错误 unsupported NSSortDescriptor selector: comparatorOfStringLengths。我尝试了NSSortDescriptor 的比较器块版本,但它不受支持。

            query.sortDescriptors = [
                NSSortDescriptor.init(key: "word", ascending: false, selector: #selector(NSString.comparatorOfStringLengths))
            ]

以下是比较器方法签名的最新版本。我也尝试使用带有两个参数的static func,并且使用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(_:)))

【问题讨论】:

    标签: swift core-data nssortdescriptor


    【解决方案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 实体同步。

    然后在namelen 上添加索引NameLenIndex 会使获取速度更快:

    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
    

    【讨论】:

      猜你喜欢
      • 2018-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-30
      相关资源
      最近更新 更多