Ios 在SwiftUI中将@FetchRequest与核心数据一起使用时修改nil排序行为

Ios 在SwiftUI中将@FetchRequest与核心数据一起使用时修改nil排序行为,ios,swift,core-data,swiftui,Ios,Swift,Core Data,Swiftui,我正在从SwiftUI中的核心数据中提取实体,并希望按如下方式对它们进行排序: 如果有下一个日期,按升序排序 在那些有下一个日期的下面,按创建的日期对剩余的进行排序 我有: @FetchRequest(entity: MyEntity.entity(), sortDescriptors: [ NSSortDescriptor(keyPath: \MyEntity.nextDate, ascending: true), NSSortDescriptor(keyPath: \MyEn

我正在从SwiftUI中的核心数据中提取实体,并希望按如下方式对它们进行排序:

  • 如果有下一个日期,按升序排序
  • 在那些有下一个日期的下面,按创建的日期对剩余的进行排序
  • 我有:

    @FetchRequest(entity: MyEntity.entity(), sortDescriptors: [
        NSSortDescriptor(keyPath: \MyEntity.nextDate, ascending: true),
        NSSortDescriptor(keyPath: \MyEntity.dateCreated, ascending: true)
    ]) private var entities: FetchedResults<MyEntity>
    
    我还尝试使用包含比较器块的
    NSSortDescriptor
    API,但是这会与

    异常:“不支持的NSSortDescriptor(不支持比较器块 支持的“


    如何实现所需的排序行为?

    在CoreData中,排序仅使用NSString类中的方法,如“compare:”或“localizedStandardCompare:”之类的方法

    由于您无法重写这些方法,甚至在大多数情况下都无法更改它们,所以您可以考虑其他解决方案。 您可以设置一个

    特殊日期,而不是“Nil”日期,如果所需数据为“Nil”,该日期将非常晚。通过这种方式,您可以将这些日期排序到底部。
    您不能显示这些特殊日期,也不能在SwiftView中将其显示为“无”


    您可以只玩
    NSString
    游戏,而不是
    子类

    。@FetchRequest使用排序描述符作为fetch请求的一部分,因此您不能在fetch请求的定义中使用比较器块(至少不能与SQLite存储一起使用)。但是,在处理视图的
    主体
    的过程中,可以使用以下方法对提取(
    实体
    )的结果进行排序:

    var主体:一些视图{
    VStack{
    名单{
    ForEach(self.entities.sorted)(按:{first,second in.)
    
    如果first.nextDate==nil&&second.nextDate==nil{return(first.dateCreated)显示如何在@FetchRequest中调用子类NSSortDescriptor,please@E.Coms更新
    final class NilsLastSortDescriptor: NSSortDescriptor {
        override func copy(with zone: NSZone? = nil) -> Any {
            return NilsLastSortDescriptor(key: self.key, ascending: self.ascending, selector: self.selector)
        }
    
        override var reversedSortDescriptor: Any {
            return NilsLastSortDescriptor(key: self.key, ascending: !self.ascending, selector: self.selector)
        }
    
        override func compare(_ object1: Any, to object2: Any) -> ComparisonResult {
            if (object1 as AnyObject).value(forKey: self.key!) == nil && (object2 as AnyObject).value(forKey: self.key!) == nil {
                return .orderedSame
            }
            if (object1 as AnyObject).value(forKey: self.key!) == nil {
                return .orderedDescending
            }
            if (object2 as AnyObject).value(forKey: self.key!) == nil {
                return .orderedAscending
            }
            return super.compare(object1, to: object2)
        }
    }
    
    var body: some View {
            VStack {
            List{
                ForEach(self.entities.sorted(by: { first, second in
                    if first.nextDate == nil && second.nextDate == nil { return (first.dateCreated <= second.dateCreated) }
                    if first.nextDate == nil { return false }
                    if second.nextDate == nil { return true }
                    if first.nextDate! == second.nextDate! { return (first.dateCreated <= second.dateCreated) }
                    return (first.nextDate! < second.nextDate!)
                }), id: \.self) { myEntity in
                    // Your code for your cells...
                    ...
                }
            }
        }
    }