Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I sort a swift array containing instances of NSManagedObject subclass by an attribute value (date)

I'm trying to sort an array as laid out in the accepted answer to this question, but am running into the problem which Isuru mentions in the comments on that answer. Namely, the code which should sort the array by the entity's "date" attribute brings the compiler complaint "could not find member 'date'"

Here is the NSManagedObject subclass describing the entity:

import Foundation import CoreData  @objc(Entry) class Entry: NSManagedObject {      @NSManaged var date: NSDate     @NSManaged var reflections: AnyObject     @NSManaged var contactComment: NSSet     @NSManaged var person: NSSet      override func awakeFromInsert() {         let now:NSDate = NSDate()         self.date = now;     } } 

And here is the code which tries to sort the array:

lazy var entries:[Entry] = {     var days:[Entry] = self.managedObjectContext!.requestEntity("Entry")as [Entry]     days.sort({$0.date < $1.date})      var today:Entry = days.last!     println(today.date)     return days }() 

Note that in the latter part of that code, I am able to access and log the "date" property for one of the entries, and the Compiler doesn't have a problem with it.

Is my syntax for sorting correct? Is there another issue with this code I'm not seeing?

like image 670
Steven Hovater Avatar asked Oct 26 '14 20:10

Steven Hovater


People also ask

How do you sort an array of data in Swift?

To sort the array we use the sort() function. This function is used to sort the elements of the array in a specified order either in ascending order or in descending order. It uses the “>” operator to sort the array in descending order and the “<” operator to sort the array in ascending order.

How do I sort a string in Swift?

Strings in Swift conform to the Comparable protocol, so the names are sorted in ascending order according to the less-than operator ( < ). To sort the elements of your sequence in descending order, pass the greater-than operator ( > ) to the sorted(by:) method.

How do I set up NSManagedObject?

From the Xcode menu bar, choose Editor > Create NSManagedObject Subclass. Select your data model, then the appropriate entity, and choose where to save the files. Xcode places both class and properties files into your project.


2 Answers

This is partly an issue with the Swift compiler not giving you a helpful error. The real issue is that NSDate can't be compared with < directly. Instead, you can use NSDate's compare method, like so:

days.sort({ $0.date.compare($1.date) == NSComparisonResult.OrderedAscending }) 

Alternatively, you could extend NSDate to implement the Comparable protocol so that it can be compared with < (and <=, >, >=, ==):

public func <(a: NSDate, b: NSDate) -> Bool {     return a.compare(b) == NSComparisonResult.OrderedAscending }  public func ==(a: NSDate, b: NSDate) -> Bool {     return a.compare(b) == NSComparisonResult.OrderedSame }  extension NSDate: Comparable { } 

Note: You only need to implement < and == and shown above, then rest of the operators <=, >, etc. will be provided by the standard library.

With that in place, your original sort function should work just fine:

days.sort({ $0.date < $1.date }) 
like image 189
Mike S Avatar answered Sep 19 '22 20:09

Mike S


In Swift 3, dates are now directly comparable:

let aDate = Date() let bDate = Date()  if aDate < bDate {      print("ok") } 

Old swift: An alternative would be to sort on the timeIntervalSince1970 property of the date object, which is directly comparable.

days.sort({$0.date.timeIntervalSince1970 < $1.date.timeIntervalSince1970}) 
like image 27
Fred Faust Avatar answered Sep 21 '22 20:09

Fred Faust