2014-09-10 12 views
22

W Objective-C mogę posortować NSArray użyciu tego komunikatu:Sortuj NSArray z sortedArrayUsingComparator

NSArray *sortedArray = [persons sortedArrayUsingComparator:^NSComparisonResult(Person *p1, Person *p2) { 
    return [p1.name compare:p2.name]; 
}]; 

jestem w stanie odtworzyć tego samego komunikatu z Swift. Wszystko, co znalazłem, to używanie Array.

Odpowiedz

35

Można wykorzystanie Swift's built in sort functions lub, ponieważ tablica Swift jest zmostkowana do NSArray, możesz zadzwonić pod numer sortedArrayUsingComparator bezpośrednio z Swift.

Korzystanie Swift sorted funkcję:

var sortedArray = sorted(persons) { 
    (obj1, obj2) in 

    // The downcast to Person is only needed if persons is an NSArray or a Swift Array of AnyObjects 
    let p1 = obj1 as Person 
    let p2 = obj2 as Person 
    return p1.name < p2.name 
} 

Lub przy NSArray „s sortedArrayUsingComparator:

var sortedArray = persons.sortedArrayUsingComparator { 
    (obj1, obj2) -> NSComparisonResult in 

    let p1 = obj1 as Person 
    let p2 = obj2 as Person 
    let result = p1.name.compare(p2.name) 
    return result 
} 
+0

'NSComparisonResult' jest teraz' ComparisonResult'. – ThomasW

9

Więc spróbuj po prostu napisać to samo z Swift:

var sortedArray:NSArray = 
persons.sortedArrayUsingComparator(){(p1:AnyObject!, p2:AnyObject!) -> NSComparisonResult in 

    if (p1 as Person).name > (p2 as Person).name { 
     return NSComparisonResult.OrderedDescending 
    } 
    if (p1 as Person).name < (p2 as Person).name { 
     return NSComparisonResult.OrderedAscending 
    } 
    return NSComparisonResult.OrderedAscending 
} 

Test (plac zabaw):

class Person{ 
    var name:String? 
} 

var p1:Person = Person() 
p1.name = "a"  

var p3:Person = Person() 
p3.name = "c" 

var p2:Person = Person() 
p2.name = "b" 

var persons:NSArray = [p1,p3,p2] 

var sortedArray:NSArray = persons.sortedArrayUsingComparator(){ 

    (p1:AnyObject!, p2:AnyObject!) -> NSComparisonResult in 

    if (p1 as Person).name > (p2 as Person).name { 
     return NSComparisonResult.OrderedDescending 
    } 
    if (p1 as Person).name < (p2 as Person).name { 
     return NSComparisonResult.OrderedAscending 
    } 
    return NSComparisonResult.OrderedAscending 
    } 

for item:AnyObject in sortedArray{ 
    println((item as Person).name) 
} 

wyjściowa:

Optional("a") 
Optional("b") 
Optional("c") 
13

Nie ma potrzeby, aby uniknąć Swift Array.

Został zmostkowany w obu kierunkach z NSArray, więc dla bardziej bezpiecznego kodu najlepiej jest wykonywać pracę z tablicami Swift i mostem tylko wtedy, gdy jest to potrzebne do współdziałania z interfejsami API ObjC. (W większości importowanych API Swift automatycznie konwertuje NSArray do [AnyObject], więc nie trzeba nawet zlikwidować bardzo często).

Zakładając tablicę persons jest [AnyObject] masz z innego API, można wyciąć na kwota typ odlewniczej w stosunku do innych odpowiedzi oddając tablicę pierwszy:

let sortedPersons = sorted(persons as [Person]) { $0.name < $1.name } 
// sortedPersons has inferred type [Person] 

Ponadto, ponieważ używasz bloku komparatora tylko do sortowania na specyficzną właściwość klasy Person, można zrobić lepiej użyć sortowania deskryptory:

let sortedPersons = (persons as NSArray).sortedArrayUsingDescriptors([ 
    NSSortDescriptor(key: "name", ascending: true) 
]) 

(The persons as NSArray część może nie być konieczne, jeśli persons pochodził z objc API).

zależności od klasy Person jest realizowany, sortowania z deskryptorów może produkować bardziej efektywnego sortowania na backend. Na przykład, jeśli jest to obiekt zarządzany Core Data, sortowanie za pomocą deskryptorów może wygenerować zapytanie SQL, które będzie wykonywane szybko w bazie danych i zużywa mało pamięci, natomiast sortowanie przy zamknięciu komparatora wymaga utworzenia instancji każdego obiektu z bazy danych tylko po to, aby ocenić zamknięcie względem każdego z nich. .

+0

Dziękuję bardzo @rickster. To było dla mnie przydatne. – Raja

+0

Drugi zadziałał dla mnie ... zajął !! – NSPratik

0

W Swift można użyć nowego podejścia. Spróbuj użyć posortowanej metody zamiast sortowaćArrayUsingComparator w ten sposób ...

var sortedArray = results.sorted { 
    (obj1, obj2) -> Bool in 
    return obj1.count! > obj2.count! 
} 
0

w przypadku gdy masz niestandardowego obiektu i chcesz, aby posortować według daty

let sortedArray = self.posts.sorted { 
      (obj1, obj2) -> Bool in 
      return (obj1 as! PostModel).orderCancellionDate.compare((obj2 as! PostModel).orderCancellionDate) == .orderedDescending 
     }