2014-10-26 12 views
43

Sto cercando di ordinare un array come disposto in the accepted answer to this question, ma sto correndo nel problema che Isuru menziona nei commenti su questo risposta. Vale a dire, il codice che dovrebbe ordinare l'array per attributo "data" dell'entità porta la denuncia del compilatore "non riusciva a trovare membro 'data'"Come ordinare un array rapido contenente istanze di sottoclasse NSManagedObject di un valore di attributo (data)

Qui è la sottoclasse NSManagedObject descrivendo 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; 
    } 
} 

E ecco il codice che cerca di ordinare l'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 
}() 

si noti che nella seconda parte di tale codice, sono in grado di accedere e accedere alla proprietà "date" per una delle voci, e il compilatore doesn avere un problema con esso

La sintassi per l'ordinamento è corretta? C'è un altro problema con questo codice che non vedo?

risposta

124

Questo è in parte un problema con il compilatore Swift che non ti dà un errore utile. Il vero problema è che NSDate non può essere confrontato direttamente con <. Invece, è possibile utilizzare NSDate 's metodo compare, in questo modo:

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

In alternativa, si potrebbe estendere NSDate per l'attuazione del protocollo di Comparable in modo che possa essere confrontato con < (e <=, >, >=, ==) :

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

Nota: Hai solo bisogno di implementare < e == e mostrato sopra, quindi il resto degli operatori <=, >, ecc. Saranno forniti dalla libreria standard.

Con questo in luogo, la vostra funzione di ordinamento originale dovrebbe funzionare bene:

days.sort({ $0.date < $1.date }) 
+0

Questo funziona perfettamente per piccole quantità di dati, ma quando si dispone di grandi quantità ci vuole un po 'di tempo per caricare. Esiste un metodo più efficiente? – nsij22

+0

@ nsij22 dato che stiamo parlando di 'NSManagedObject's, allora questi oggetti provengono probabilmente da un archivio dati principale.In tal caso, la cosa più efficace da fare è probabilmente ordinare i dati tramite la richiesta di recupero dei dati di base. Dai un'occhiata a 'NSFetchRequest.sortDescriptors': https://developer.apple.com/library/mac/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSFetchRequest_Class/index.html#//apple_ref/occ/instp/NSFetchRequest/ sortDescriptors –

16

In Swift 3, le date sono ora direttamente comparabili:

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

if aDate < bDate { 

    print("ok") 
} 

Vecchio rapida: Un'alternativa sarebbe essere in ordine sulla proprietà timeIntervalSince1970 dell'oggetto date, che è direttamente comparabile.

days.sort({$0.date.timeIntervalSince1970 < $1.date.timeIntervalSince1970}) 
+0

Non so perché questa non è la soluzione accettata –

+0

Ci ho pensato solo quando avevo bisogno della stessa cosa e ho visto la prima frase della risposta accettata, che era molto più tarda di quando è stata pubblicata la risposta accettata. –

10

In swift2.1 uso questo le linee di codice

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

I avente un dizionario le cui chiavi sono nel formato data quindi devo ordinare la dizionario per data. Ho copiato tutte le chiavi in ​​nsarray e poi ho ordinato quell'array usando il seguente codice.

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) 
Problemi correlati