[英]Modify nil sort behavior when using @FetchRequest with Core Data in SwiftUI
我正在从 SwiftUI 中的核心数据中获取实体,并希望像这样对它们进行排序:
我有:
@FetchRequest(entity: MyEntity.entity(), sortDescriptors: [
NSSortDescriptor(keyPath: \MyEntity.nextDate, ascending: true),
NSSortDescriptor(keyPath: \MyEntity.dateCreated, ascending: true)
]) private var entities: FetchedResults<MyEntity>
问题是那些没有下一个日期的人都排在那些下一个日期非零的人之上,如 this 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(不支持比较器块)”
我怎样才能实现所需的排序行为?
@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 值。 它可能也可以写得更漂亮 - 但我希望你明白了。
请注意它在 memory 中排序,因此不知道此解决方案的性能和/或 memory 影响。
在 CoreData 中,排序仅使用 NSString class 中的方法,例如“compare:”或“localizedStandardCompare:”之类的方法。
由于在大多数情况下您无法覆盖这些方法甚至无法更改它们,因此您可以考虑其他解决方法。
如果所需数据为“无”,您可以设置一个非常晚的Special Date
,而不是“无”日期。 通过这种方式,您可以将这些日期排序到底部。 您可能不会显示这些特殊日期,或在 SwiftView 中将它们显示为“Nil”。
你可以只玩NSString
游戏,而不是subclass
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.