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?
In the
NSManagedObject
subclass add an attribute (of course also in the model)@NSManaged var itemAdded : Date
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 usingSet(array)
, this will remove the duplicates - turn the
Set
back to an array by usingArray(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
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
Case Insensitive Matching Search in String Array Swift 3
Swift 3: Transfer Utility Enumeratetoassignblocks Method Signature
How to Get HTML5 Video Thumbnail Without Using Poster on Safari or iOS
Nsmanagedobject Setter Giving Me [ Myobject Setname:]: Unrecognized Selector Sent to Instance
Background Image Not Displaying Correctly in iOS
How to Add Action to Uialertview in Swift (iOS 7)
How to Set Gradient Background Transparency on iOS Safari
Cancel All Operations + Afnetworking 3.0
Adding an Skscene to a Uiviewcontroller
How Is a Swift Cgvector Created with Dx and Dy (Derivative)
Apple Doesn't Recognize Imgur's Https
Swift Package Manager Issues with Unversioned Packages (Example: Firebase-Ios-Sdk)
Xcode6 Goldmaster Submitting Build Failed with Error
Invalid Transaction Receipt Returned by Appstorereceipturl (Nsdata), in iOS 7
Cannot Pass Immutable Value as Inout Argument: Literals Are Not Mutable, Why