Reputation: 31
I am building an app in Swift and I want to display a list with the closest birthdays appearing first on the screen.
e.g. if I have 3 dates (21st of Dec, 21st of May, 21st of Nov) and today is 31st of May. The order shall be 21st of Nov, 21st of Dec and 21st of May.
I am using CoreData and I have an entity called Entry having a date:
extension Entry {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Entry> {
return NSFetchRequest<Entry>(entityName: "Entry")
}
@NSManaged public var date: Date?
}
And the apparition is made with NSSortDescriptor:
override func viewWillAppear(_ animated: Bool) {
if let context = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext {
let request: NSFetchRequest<Entry> = Entry.fetchRequest()
request.sortDescriptors = [NSSortDescriptor(key: "date", ascending: true)]
if let entriesFromCoreData = try? context.fetch(request) {
entries = entriesFromCoreData
tableView.reloadData()
}
}
}
I have tried the following, but (1) is giving me a fatal error while extracting a String from KeyPath Swift.KeyPath and (2) is not making the proper sort, taking into consideration the year.
(1)
extension Entry {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Entry> {
return NSFetchRequest<Entry>(entityName: "Entry")
}
@NSManaged public var date: Date?
var nextBirthday: Date { date?.nextBirthday ?? .distantFuture }
}
extension Date {
var isInToday: Bool { Calendar.current.isDateInToday(self) }
var nextBirthday: Date {
isInToday ? self : Calendar.current.nextDate(after: Date(), matching: Calendar.current.dateComponents([.month, .day, .hour, .minute], from: self), matchingPolicy: .nextTime)!
}}
override func viewWillAppear(_ animated: Bool) {
if let context = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext {
let request: NSFetchRequest<Entry> = Entry.fetchRequest()
request.sortDescriptors = [NSSortDescriptor(keyPath: \Entry.nextBirthday, ascending: true)]
if let entriesFromCoreData = try? context.fetch(request) {
entries = entriesFromCoreData
tableView.reloadData()
}
}
}
(2)
extension NSDate {
dynamic var nextOccurrence : NSDate {
let calendar = Calendar.current
let components = calendar.dateComponents([.month, .day], from: self as Date)
return calendar.nextDate(after: Date(), matching: components, matchingPolicy: .nextTime)! as NSDate
}}
NSSortDescriptor(key: "date.nextOccurrence", ascending: true)
Upvotes: 2
Views: 59