How to Sort Core Data Array Based on Date Entered

How to sort Core Data array based on Date Entered

Yes, you need a second attribute declared as non-optional Date for example dateCreated. In the NSManagedObject subclass override awakeFromInsert to assign the current date when the record is created.

override func awakeFromInsert() {
super.awakeFromInsert()
dateCreated = Date()
}

Then you can sort

request.sortDescriptors = [NSSortDescriptor(key: "dateCreated", ascending: true)]

in ascending order means the oldest entry comes first.

Swift sort core data by date (not just time)

Swift 3

var sdSortDate = NSSortDescriptor.init(key: "date", ascending: false)
fr.sortDescriptors = [sdSortDate]
let result4 = try! context.fetch(fr)

I tested it in Swift 3, works well

[<NSManagedObject: 0x618000089060> (entity: CoreDate; id: 0x61800002c460 <x-coredata://E7D9FD6F-5DCF-464B-93BF-D1609BF35695/CoreDate/p3> ; data: {
date = "2017-02-09 21:35:19 +0000";
}), <NSManagedObject: 0x61800008b680> (entity: CoreDate; id: 0x60000002c140 <x-coredata://E7D9FD6F-5DCF-464B-93BF-D1609BF35695/CoreDate/p1> ; data: {
date = "2017-02-06 04:41:59 +0000";
}), <NSManagedObject: 0x60800008c080> (entity: CoreDate; id: 0x60800002d460 <x-coredata://E7D9FD6F-5DCF-464B-93BF-D1609BF35695/CoreDate/p2> ; data: {
date = "2017-02-17 18:28:39 +0000";
})]

After sort

[<NSManagedObject: 0x61800008b680> (entity: CoreDate; id: 0x60000002c140 <x-coredata://E7D9FD6F-5DCF-464B-93BF-D1609BF35695/CoreDate/p1> ; data: {
date = "2017-02-06 04:41:59 +0000";
}), <NSManagedObject: 0x618000089060> (entity: CoreDate; id: 0x61800002c460 <x-coredata://E7D9FD6F-5DCF-464B-93BF-D1609BF35695/CoreDate/p3> ; data: {
date = "2017-02-09 21:35:19 +0000";
}), <NSManagedObject: 0x60800008c080> (entity: CoreDate; id: 0x60800002d460 <x-coredata://E7D9FD6F-5DCF-464B-93BF-D1609BF35695/CoreDate/p2> ; data: {
date = "2017-02-17 18:28:39 +0000";
})]

Sort FetchRequest by last item added to Core data

The above code is correct. But the problem is you have been sorting based on the title of your objects.

You can add another variable to your object as timeAdded, where you can store your object's creation time. And you can fetch your objects based on timeAdded.

Is there a way to keep the sorting in core data in the time order the objects are added?

  1. In the NSManagedObject subclass add an attribute (of course also in the model)

    @NSManaged var itemAdded : Date
  2. Override awakeFromInsert

    override func awakeFromInsert() {
    super.awakeFromInsert()
    itemAdded = Date()
    }

Now you can sort by itemAdded

Swift coredata sort by relationship property?

A to-many relationship is always an unordered set.

An option is to add a computed property sortedPhotos in Place. photos represents the relationship and is supposed to be declared as native Set<Photo>:

var sortedPhotos : [Photo] {
return photos.sorted{ $0.creationDate < $1.creationDate }
}

Another option – if you want to fetch all photos of one specific place - fetch the Photo entity with predicate "place.name == %@", place.name and add a sort descriptor.

Sorting Filtered Data by Date

You don't need to "save" the elements in a set - you can just:

  • turn the array into a Set by simply using Set(array), this will remove the duplicates
  • turn the Set back to an array by using Array(yourSetHere)
  • sort it
  • turn the array of dates into an array of strings

Here's what uniqueBankDates should look like (WdModel shall be conform to Hashable):

    var uniqueBankDates: [String] {
Array(Set(wdvm.wdArray)) // This will remove duplicates, but WdModel needs to be Hashable
.sorted { $0.wdDate < $1.wdDate } // Compare dates
.compactMap {
$0.wdDate.formatted(date: .abbreviated, time: .omitted) // Return an array of formatted the dates
}
}

Sort NSSortDescriptor by Month of date. Swift

You can create a custom sort to get your dates sorted by incoming birthday and pass your collection sorted to your ForEach method:

extension Collection where Element == Birthday {
func sortedByIncomingBirthday() -> [Element] {
sorted {
// lhs date is today or is in the future
($0.date.month, $0.date.day) >= (Date().month, Date().day) ?
// rhs date is today or is in the future
($1.date.month, $1.date.day) >= (Date().month, Date().day) ?
// sort them by a month day order
($0.date.month, $0.date.day) < ($1.date.month, $1.date.day) :
// otherwise is in increasing order
true :
// lhs date is in the past
// sort them by a month day order
($0.date.month, $0.date.day) < ($1.date.month, $1.date.day)
}
}
}

ForEach(birthdays.sortedByIncomingBirthday(), id: \.self) { birthday in

Another option is to extend Birthday and add a nextBirthday property this way you can sort it using it as a keyPath for your NSSortDescriptor:

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)!
}
}

extension Birthday {
var nextBirthday: Date { date.nextBirthday }
}

NSSortDescriptor(keyPath: \Birthday.nextBirthday, ascending: true)

edit/update:

if Birthday date property is optional don't force unwrap its value:

extension Birthday {
var nextBirthday: Date { date?.nextBirthday ?? .distantFuture }
}

and the first approach would need to deal with it as well:

extension Collection where Element == Birthday {
func sortedByIncomingBirthday() -> [Element] {
sorted { lhs, rhs in
if lhs.date == nil { return false }
let lhs = lhs.date ?? .distantFuture
let rhs = rhs.date ?? .distantFuture
// lhs date is today or is in the future
return (lhs.month, lhs.day) >= (Date().month, Date().day) ?
// rhs date is today or is in the future
(rhs.month, rhs.day) >= (Date().month, Date().day) ?
// sort them by a month day order
(lhs.month, lhs.day) < (rhs.month, rhs.day) :
// otherwise is in increasing order
true :
// lhs date is in the past
// sort them by a month day order
(lhs.month, lhs.day) < (rhs.month, rhs.day)
}
}
}

Save core data date as a array

You can use Transformable type to save an Array.

I've use the same approach to save Dictionaries

Sample Image

Then you can change Codegen to Manual/None, click on Editor->Create NSManagedobject Subclass (top of the screen).

And Xcode will generate Data class for you



Related Topics



Leave a reply



Submit