2015-05-31 11 views
6

Ich arbeite an einer iOS App und ich habe Daten in CoreData gespeichert, die ich in eine UITableView laden werde. Die Datenentitäten haben ein Attribut mit der Bezeichnung id, das eine Zeichenkette ist, die eine A enthält, gefolgt von einer Nummer (d. H. "A1" "A2" usw.).NSSortDescriptor in Swift

Wenn ich diesen Code verwenden, zum Sortieren, I am Ende mit der Tabelle lexikographisch sortiert werden (dh "A1" "A10" "A11" "A12", "A2" "A3" etc)

let sortDescriptor = NSSortDescriptor(key: "id", ascending: true) 
fetchRequest.sortDescriptors = [sortDescriptor] 

Was ich wirklich will, ist, dass es numerisch sortiert ist, wie Sie vielleicht erwarten. Wie gehe ich dabei vor? Ich weiß, dass ein NSComparator als Argument zu NSSortDescriptor hinzugefügt werden kann, aber ich kann nicht für das Leben von mir es herausfinden. Vielen Dank im Voraus für jede Hilfe!

Antwort

10

Sortierdeskriptoren in einer (SQLite-basierten) Core Data Fetch-Anfrage kann nicht verwenden benutzerdefinierte Vergleicher und nur eine begrenzte Reihe von "eingebauten" Vergleich Methoden. Dies wird dokumentiert in Fetch Predicates and Sort Descriptors im „Core Data Programming Guide“:

... Der SQL-Speicher, auf der anderen Seite, stellt das Prädikat und sortieren Deskriptoren SQL und wertet das Ergebnis in der Datenbank selbst . Dies ist in erster Linie für die Leistung, aber es bedeutet, dass die Bewertung in einer Umgebung außerhalb von Cocoa passiert, und so Sortierdeskriptoren (oder Prädikate), die auf Cocoa beruhen, kann nicht funktionieren. Die unterstützten Art Selektoren sind compare: und caseInsensitiveCompare:, localizedCompare:, localizedCaseInsensitiveCompare: und localizedStandardCompare: (die Letzteres ist Finder artige Sortierung, und was die meisten Menschen sollten die meisten die Zeit nutzen). Darüber hinaus können Sie keine transienten Eigenschaften mithilfe des SQLite-Speichers sortieren.

Glücklicherweise gibt es eine, die Ihre Bedürfnisse passen sollte:

let sortDescriptor = NSSortDescriptor(key: "id", ascending: true, 
         selector: "localizedStandardCompare:") 

localizedStandardCompare: hat ein „Finder-like“ -Vergleich und insbesondere behandelt Ziffern innerhalb von Strings nach ihrem Zahlenwert.

Für Swift 2.2/Xcode 7.3 und später:

let sortDescriptor = NSSortDescriptor(key: "id", ascending: true 
         selector: #selector(NSString.localizedStandardCompare)) 
+0

Genau das, was ich brauchte. Vielen Dank! –

+0

das neue Format scheint .. NSSortDescriptor (Schlüssel: "ID", aufsteigend: True, Selektor: #Selector (NSString.localizedCompare (_ :))) –

+0

@JosephAstrahan: Danke, aktualisiert! –

1

Der Swifty Weg:

var arr = ["A1", "A10", "A11", "A12", "A2", "A3"] 
arr.sort {dropFirst($0).toInt() < dropFirst($1).toInt()} 

So könnten Sie das direkt verwenden oder sie als Grundlage des Blocks für Ihren Komparator verwenden. Wenn Sie darauf bestehen, dies in dem zu tun, was effektiv Objective-C ist, können Sie NSString compare:options: verwenden, wobei options:NSNumericSearch enthält.

+2

Dies würde funktionieren, um die Daten zu sortieren * nach * holen sie, aber nicht als Sortierdeskriptor in einer Core Data Fetch-Anfrage. –

0

Swift 3

let sortDescriptor = NSSortDescriptor(key: "id", ascending: true, selector: #selector(NSString.localizedCaseInsensitiveCompare))

hoffen, dass es

0

Für swift3

Schlüssel hilft, ist

result: Bool = 0 < "string1".localizedCompare("string2").rawValue 

Verwenden ähnliche

[some string array].sorted { return 0 < "string1".localizedCompare("string2").rawValue } 
0

Warum bei obj-c Stil NSSortDescriptor, In swift stören können wir schön Art Swift hohen Auftragsfunktionen - Xcode 8.x swift 3.x

class Person: NSObject { 
    let firstName: String 
    let lastName: String 
    let age: Int 

    init(firstName: String, lastName: String, age: Int) { 
     self.firstName = firstName 
     self.lastName = lastName 
     self.age = age 
    } 
    override var description: String { 
     return "\(firstName) \(lastName)" 
    } 
} 

let a = Person(firstName: "a", lastName: "b", age: 24) 
let b = Person(firstName: "c", lastName: "d", age: 27) 
let c = Person(firstName: "e", lastName: "f", age: 33) 
let d = Person(firstName: "g", lastName: "h", age: 31) 
let peopleObject = [d, b, a, c] 
//SWIFTY 
let sortedByFirstNameSwifty = peopleObject.sorted(by: { $0.firstName < $1.firstName }) 
print(sortedByFirstNameSwifty)//prints[a b, c d, e f, g h] 


//Objective c way 
let firstNameSortDescriptor = NSSortDescriptor(key: "firstName", ascending: true, selector: #selector(NSString.localizedStandardCompare(_:))) 
let sortedByFirstName = (peopleObject as NSArray).sortedArray(using: [firstNameSortDescriptor]) 
print(sortedByFirstName)//prints [a b, c d, e f, g h] 
Verwandte Themen