我正在从SwiftUI的Core Data中获取实体,并希望对它们进行排序:
我有:
@FetchRequest(entity: MyEntity.entity(), sortDescriptors: [
NSSortDescriptor(keyPath: \MyEntity.nextDate, ascending: true),
NSSortDescriptor(keyPath: \MyEntity.dateCreated, ascending: true)
]) private var entities: FetchedResults<MyEntity>
问题是,没有下一个日期的那些排序都比下一个没有空日期的排序高,如本other question所示。
我试图对NSSortDescriptor
进行子类化,以将nil
的值移到最后,但是它从未调用任何重写的函数。
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)
}
}
我还尝试使用包含比较器块的NSSortDescriptor
API,但这会因
异常:“不受支持的NSSortDescriptor(比较器块不 支持)”
如何实现所需的排序行为?
答案 0 :(得分:1)
@FetchRequest将排序描述符用作获取请求的一部分,因此,您不能在获取请求的定义中使用比较器块(至少,不适用于SQLite存储)。但是,您可以使用sorted(by:)对获取的entities
的结果进行排序,作为对视图body
的处理的一部分:
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...
...
}
}
}
}
为简单起见,我假设dateCreated
是非可选的。如果不是,则需要修改谓词以处理nil值。也可能会写得更简洁一些-但我希望您能明白。
仅需注意其在内存中的排序,因此不知道此解决方案的性能和/或内存影响。
答案 1 :(得分:0)
在CoreData中,仅使用NSString类中的方法(例如“ compare:”或“ localizedStandardCompare:”)进行排序。
由于在大多数情况下您无法覆盖这些方法,甚至无法更改它们,因此您可以考虑其他解决方法。
您可以设置Special Date
而不是“ Nil”日期,如果所需数据为“ Nil”,那将很晚。通过这种方式,您可以将这些日期排序到底部。
您可能不会显示这些特殊日期,也不会在SwiftView中将其显示为“无”。
您只能玩NSString
游戏,不能玩subclass