web-dev-qa-db-fra.com

Comment trier un tableau Swift contenant des instances de la sous-classe NSManagedObject par valeur d'attribut (date)

J'essaie de trier un tableau comme indiqué dans la réponse acceptée à cette question , mais je rencontre le problème que Isuru mentionne dans les commentaires sur cette réponse. A savoir, le code qui doit trier le tableau par l'attribut "date" de l'entité apporte la plainte du compilateur "n'a pas pu trouver le membre 'date'"

Voici la sous-classe NSManagedObject décrivant l'entité:

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;
    }
}

Et voici le code qui essaie de trier le tableau:

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

Notez que dans la dernière partie de ce code, je suis en mesure d'accéder à la propriété "date" et de la journaliser pour l'une des entrées, et le compilateur n'a pas de problème avec elle.

Ma syntaxe de tri est-elle correcte? Y a-t-il un autre problème avec ce code que je ne vois pas?

45
Steven Hovater

C'est en partie un problème avec le compilateur Swift ne vous donnant pas une erreur utile. Le vrai problème est que NSDate ne peut pas être comparé avec < directement. Au lieu de cela, vous pouvez utiliser la méthode NSDate de compare, comme ceci:

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

Vous pouvez également étendre NSDate pour implémenter le protocole Comparable afin qu'il puisse être comparé à < (et <=, >, >=, ==):

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 { }

Remarque: Il vous suffit d'implémenter < et == et illustré ci-dessus, puis reste des opérateurs <=, >, etc. seront fournis par la bibliothèque standard.

Avec cela en place, votre fonction de tri d'origine devrait très bien fonctionner:

days.sort({ $0.date < $1.date })
124
Mike S

Dans Swift 3, les dates sont désormais directement comparables:

let aDate = Date()
let bDate = Date()

if aDate < bDate {

    print("ok")
}

Old Swift: Une alternative serait de trier sur la propriété timeIntervalSince1970 de l'objet date, qui est directement comparable.

days.sort({$0.date.timeIntervalSince1970 < $1.date.timeIntervalSince1970})
16
Fred Faust

Dans Swift2.1 utilise ces lignes de code

array.sortInPlace({ $0.date.compare($1.date) == NSComparisonResult.OrderedAscending })
10
Phani Sai

Update__ Swift 4,

let sortedData = dataToSort.sorted(by: { (obj1, obj2) -> Bool in             
   return obj1.date < obj2. date
})
1
Sagar Thukral

J'ai un dictionnaire dont les clés sont au format date donc je dois trier le dictionnaire par date. j'ai copié toutes les clés dans nsarray puis trié ce tableau en utilisant le code suivant.

let keys : NSArray = stackedBarDataDict.allKeys // stackedBarDataDict is Data Dictionary
    let dataArray = NSMutableArray()
    for index in 0...(stackedBarDataDict.allKeys.count - 1)
    {
        let dateone = keys.objectAtIndex(index)
        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd"
        let date1 = dateFormatter.dateFromString(dateone as! String)
        dataArray.addObject(date1!)
    }
    let array : NSArray = (dataArray as NSArray)
        let sortedArray = array.sortedArrayUsingComparator {
        (obj1, obj2) -> NSComparisonResult in

        let p1 = obj1 as! NSDate
        let p2 = obj2 as! NSDate
        let result = p1.compare(p2)
        return result
    }
    print(sortedArray)
0
Amol Pokale