2017-03-06 3 views
1

Ich habe eine NSFetchedResultsController, die eine UITableViewController mit Appointment Entities, die unter anderem eine Eigenschaft dateTime haben.Sortieren nach (heute vor oder nach) in NSSortDescriptor

Mein Ziel ist es, eine Liste von Terminen wie folgt sortiert zu haben:

  1. Heute
  2. Morgen
  3. Morgen
  4. Gestern
  5. Tag vor gestern

Mit anderen Worten: Erster sor t ob es vor oder nach heute ist, dann auf dateTime. Also zuerst sortieren auf (dateTime > %TODAY%), dann auf dateTime selbst (Zukunft aufsteigend, absteigend).

Gibt es eine Möglichkeit, dies zu tun? Mein Problem ist, dass ich% TODAY% nicht in einem Sortierungsdeskriptor verwenden kann, aber vielleicht gibt es eine andere Möglichkeit, dasselbe visuelle Ergebnis zu erzielen.

AKTUALISIEREN: Beachten Sie, dass die akzeptierte Antwort mit einer NSFetchedResultsController nicht möglich ist. Ich wählte eine andere Lösung und bestellte die Appointments, bevor ich die Ansicht zeigte. Speichern Sie das in der Datenbank, und lassen Sie die NSFetchedResultsController die Änderungen abholen.

UPDATE 2: Akzeptierte Antwort tat genau das, was ich wollte. Meine Implementierung:

let futureAppointments = appointments.filter({ $0.dateTime != nil && $0.dateTime?.compare(Date()) == .orderedDescending }) 
    .sorted(by: { $0.dateTime?.compare($1.dateTime! as Date) == .orderedAscending }) 

let pastAppointments = appointments.filter({ $0.dateTime != nil && $0.dateTime?.compare(Date()) == .orderedAscending }) 
    .sorted(by: { $0.dateTime?.compare($1.dateTime! as Date) == .orderedDescending }) 

let sorted = futureAppointments + pastAppointments 

for (index, appointment) in sorted.enumerated() { 
    appointment.order = NSNumber(integerLiteral: index) 
} 

Antwort

0

Es ist nur Idee. Mai werden Sie SortDescriptor wie folgt erstellen:

NSSortDescriptor(key: "test", ascending: true) { (v1, v2) -> ComparisonResult in 
     guard let d1 = v1 as? Date else 
     { 
      return .orderedAscending 
     } 
     guard let d2 = v2 as? Date else 
     { 
     return .orderedAscending 
     } 
     if abs(d1.timeIntervalSinceNow) < abs(d2.timeIntervalSinceNow) { return .orderedAscending } 
     if abs(d1.timeIntervalSinceNow) > abs(d2.timeIntervalSinceNow) { return .orderedDescending } 
     return .orderedSame 
} 

Ich denke, es Arbeit sein wird.

+0

Sie können einen blockbasierten Sortierdeskriptor nicht in einer fetchRequest verwenden. siehe https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/PersistentStoreFeatures.html#//apple_ref/doc/uid/TP40001075-CH23-SW1 –

+0

Wie Jon sagte, kann ich nicht verwenden das, aber es brachte mich dazu, an eine andere Lösung zu denken, die mit Ihrem Sortierungsdeskriptor vor dem Holen geordnet wurde. Jetzt habe ich eine Eigenschaft 'order', die jedes Mal gesetzt wird, wenn jemand die Ansicht öffnet. Es sind nie mehr als 10 Termine, also sehe ich keine Leistungsprobleme. Danke – Arjan

+0

@Sergey FYI deine Antwort hat nicht genau das gemacht, was ich wollte (ich machte die Frage klarer). Ich habe meine eigene Implementierung gemacht, aber wenn Sie möchten, können Sie gerne Ihre Antwort aktualisieren. – Arjan

1

Verwenden Sie zwei fetchedResultsControllers, sortiert man mit einem Prädikat aufsteigend diejenigen ohne vor heute erstellt, und ein sortiert mit einem Prädikat absteigend zukünftigen Termine auszuschließen.

Schreiben Sie eine Funktion, die zwischen dem abgerufenenResultsController-Indexpfad und dem Indexpfad des Tabellenaufrufs und umgekehrt konvertiert wird. Stellen Sie sicher, dass Sie genau wissen, mit welcher Art von indexPath Sie es zu tun haben, und es ist nicht so schwer.

+0

Hallo Jon, ich habe eigentlich eine Basisklasse 'CoreDataTableViewController', die ich nicht ändern oder für einen Bildschirm kopieren wollte, also ging ich mit einer anderen Lösung. Danke fürs Nachdenken. – Arjan