2015-05-31 16 views
6

Sto lavorando su un'app per iOS e ho dati memorizzati in CoreData che sto caricando su UITableView. Le entità di dati hanno un attributo chiamato id che è una stringa che contiene un A seguito da un numero (ad esempio "A1" "A2" ecc.).NSSortDescriptor in Swift

Quando uso questo codice selezionare, io alla fine con la tavola da ordinare lexicographically (cioè "A1" "A10" "A11" "A12" "A2" "A3", ecc)

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

Quello che voglio davvero è che sia ordinato numericamente, come ci si potrebbe aspettare. Come procedo a fare questo? So che un NSComparator può essere aggiunto come argomento a NSSortDescriptor ma non riesco a capire come funziona. Grazie in anticipo per qualsiasi aiuto!

risposta

10

Ordinare i descrittori in un (SQLite-based) Core Data prendere richiesta non può comparatori uso personalizzate e solo un insieme limitato di "built-in" di confronto metodi. Questo è documentato in Fetch Predicates and Sort Descriptors nella "Guida alla programmazione Core Data":

... Il negozio SQL, d'altra parte, compila il predicato e ordinamento descrittori a SQL e valuta il risultato nel database stesso . Questo viene fatto principalmente per le prestazioni, ma significa che la valutazione si verifica in un ambiente non Cocoa e quindi i descrittori di ordinamento (o predicati ) che si basano su Cocoa non possono funzionare. I supportati ordinamento selettori sono compare: e caseInsensitiveCompare:, localizedCompare:, localizedCaseInsensitiveCompare:, e localizedStandardCompare: (quest'ultimo è Finder-come l'ordinamento, e ciò che la maggior parte delle persone dovrebbero usare la maggior parte del del tempo). Inoltre, non è possibile ordinare le proprietà temporanee utilizzando lo store SQLite .

Fortunatamente, v'è quella che dovrebbe soddisfare le vostre esigenze:

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

localizedStandardCompare: fa un confronto "Finder-like" e in particolare Tratta cifre all'interno delle stringhe in base al loro valore numerico.

Per Swift 2.2/Xcode 7.3 e versioni successive:

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

Esattamente quello di cui avevo bisogno. Grazie! –

+0

il nuovo formato sembra essere .. NSSortDescriptor (chiave: "id", crescente: true, selettore: #selector (NSString.localizedCompare (_ :))) –

+0

@JosephAstrahan: Grazie, aggiornato! –

1

Il modo Swifty:

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

Così si potrebbe usare che direttamente, o usarlo come base del blocco per il confronto. Se si insiste a farlo in quello che è effettivamente Objective-C, è possibile utilizzare NSString compare:options: dove lo options: include NSNumericSearch.

+2

Questo potrebbe funzionare per ordinare i dati * dopo * loro recupero, ma non come una sorta descrittore in un Data Nucleo prendere richiesta. –

0

Swift 3

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

Speranza che aiuta

0

Per Swift3

chiave è

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

Usa come questo

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

Perché perdere tempo con obj-c stile NSSortDescriptor, a Swift possiamo ben sorta utilizzando Swift funzioni di ordine superiore - Xcode 8.x rapida 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] 
Problemi correlati