Como classifico um NSMutableArray com objetos personalizados?

1268

O que eu quero fazer parece bem simples, mas não consigo encontrar respostas na Web. Eu tenho um NSMutableArrayde objetos, e vamos dizer que eles são objetos de 'Pessoa'. Eu quero classificar o NSMutableArraypor Person.birthDate que é um NSDate.

Eu acho que tem algo a ver com este método:

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(???)];

Em Java, eu faria meu objeto implementar Comparable ou usar Collections.sort com um comparador personalizado embutido ... como você faz isso no Objective-C?

enferrujado
fonte

Respostas:

2299

Compare o método

Você implementa um método de comparação para seu objeto:

- (NSComparisonResult)compare:(Person *)otherObject {
    return [self.birthDate compare:otherObject.birthDate];
}

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(compare:)];

NSSortDescriptor (melhor)

ou geralmente ainda melhor:

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                           ascending:YES];
NSArray *sortedArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];

Você pode classificar facilmente por várias chaves adicionando mais de uma à matriz. Também é possível usar métodos comparadores personalizados. Dê uma olhada na documentação .

Blocos (brilhantes!)

Há também a possibilidade de classificar com um bloco desde o Mac OS X 10.6 e o ​​iOS 4:

NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
    NSDate *first = [(Person*)a birthDate];
    NSDate *second = [(Person*)b birthDate];
    return [first compare:second];
}];

atuação

o -compare: métodos baseados em bloco e serão um pouco mais rápidos, em geral, do que usar, NSSortDescriptorjá que o último depende do KVC. A principal vantagem do NSSortDescriptormétodo é que ele fornece uma maneira de definir sua ordem de classificação usando dados, em vez de código, o que facilita, por exemplo, configurar as coisas para que os usuários possam classificar um NSTableViewclicando na linha do cabeçalho.

Georg Schölly
fonte
66
O primeiro exemplo tem um erro: você compara a variável de instância birthDate em um objeto com o outro objeto, em vez de sua variável birthDate.
Martin Gjaldbaek
90
@ Martin: Obrigado! Engraçado que ninguém mais notou antes de eu receber 75 votos a favor.
Georg Schölly
76
Como esta é a resposta aceita e, portanto, provavelmente considerada definitiva pela maioria dos usuários, pode ser útil adicionar um terceiro exemplo baseado em bloco para que os usuários saibam que ela também existe.
jpswain
6
@ orange80: Eu tentei isso. Eu não tenho mais um Mac, então seria bom se você pudesse ver o código.
Georg Schölly 04/12/11
11
Se você tem um NSMutableArrayeu prefiro usar os métodos sortUsingDescriptors, sortUsingFunctionou sortUsingSelector. Na medida em que a matriz é mutável, geralmente não preciso de uma cópia classificada.
Stephan
109

Veja o NSMutableArraymétodosortUsingFunction:context:

Você precisará configurar uma função de comparação que aceite dois objetos (do tipo Person, pois você está comparando dois Personobjetos) e um parâmetro de contexto .

Os dois objetos são apenas instâncias de Person. O terceiro objeto é uma string, por exemplo, @ "birthDate".

Esta função retorna um NSComparisonResult: Retorna NSOrderedAscendingse PersonA.birthDate< PersonB.birthDate. Ele retornará NSOrderedDescendingse PersonA.birthDate> PersonB.birthDate. Finalmente, ele retornará NSOrderedSamese PersonA.birthDate== PersonB.birthDate.

Esse é um pseudocódigo aproximado; você precisará definir o que significa uma data ser "menor", "mais" ou "igual" a outra data (como comparar segundos desde a época etc.):

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  if ([firstPerson birthDate] < [secondPerson birthDate])
    return NSOrderedAscending;
  else if ([firstPerson birthDate] > [secondPerson birthDate])
    return NSOrderedDescending;
  else 
    return NSOrderedSame;
}

Se você quiser algo mais compacto, poderá usar operadores ternários:

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  return ([firstPerson birthDate] < [secondPerson birthDate]) ? NSOrderedAscending : ([firstPerson birthDate] > [secondPerson birthDate]) ? NSOrderedDescending : NSOrderedSame;
}

Inlining talvez acelere um pouco isso, se você fizer muito isso.

Alex Reynolds
fonte
9
O uso de sortUsingFunction: context: é provavelmente a maneira mais c-ish e definitivamente a mais ilegível.
Georg Schölly 30/04/09
12
Não há nada realmente errado com isso, mas acho que agora existem alternativas muito melhores.
Georg Schölly 30/04/09
6
Talvez, mas não acho que seria menos legível para alguém de um background Java que possa estar procurando algo semelhante à classe abstrata Comparator do Java, que implementa compare (Type obj1, Type obj2).
Alex Reynolds
5
Tenho a impressão de que alguns de vocês estão procurando, por qualquer motivo, criticar essa resposta perfeitamente correta, mesmo que essa crítica tenha muito pouco mérito técnico. Esquisito.
Alex Reynolds
1
@ Yar: Você pode usar a solução fornecida no primeiro parágrafo ou usar vários descritores de classificação. SortedArrayUsingDescriptors: aceita uma matriz de descritores de classificação como argumento.
Georg Schölly
62

Eu fiz isso no iOS 4 usando um bloco. Tive que converter os elementos da minha matriz do id para o meu tipo de classe. Nesse caso, era uma classe chamada Score com uma propriedade chamada points.

Além disso, você precisa decidir o que fazer se os elementos da sua matriz não forem do tipo certo; neste exemplo, acabei de retornar NSOrderedSame, no entanto, no meu código, pensei em uma exceção.

NSArray *sorted = [_scores sortedArrayUsingComparator:^(id obj1, id obj2){
    if ([obj1 isKindOfClass:[Score class]] && [obj2 isKindOfClass:[Score class]]) {
        Score *s1 = obj1;
        Score *s2 = obj2;

        if (s1.points > s2.points) {
            return (NSComparisonResult)NSOrderedAscending;
        } else if (s1.points < s2.points) {
            return (NSComparisonResult)NSOrderedDescending;
        }
    }

    // TODO: default is the same?
    return (NSComparisonResult)NSOrderedSame;
}];

return sorted;

PS: está ordenando em ordem decrescente.

Chris
fonte
6
Na verdade, você não precisa dos lançamentos "(Pontuação *)", basta fazer "Pontuação * s1 = obj1;" porque id terá todo o prazer lançar a qualquer coisa sem aviso do compilador :-)
jpswain
orange80 direito downcastingnão requer um lançamento antes da variável fraca.
Thesummersign
Você deve classificar nil vs. não-nula a parte superior ou inferior de forma consistente, de modo que o retorno final padrão pode serreturn ((!obj1 && !obj2) ? NSOrderedSame : (obj1 ? NSOrderedAscending : NSOrderedDescending))
Scott Corscadden
heh Chris, eu tentei esse código, faço uma atualização no meu programa .. pela primeira vez, faço o trabalho correto, recebi uma saída de ordem decrescente .. mas quando atualizo. (execute o mesmo código com os mesmos dados) ele mudou a ordem, não estava descendo. Digamos que eu tenha 4 objetos no meu array, 3 hv mesmos dados, 1 é diferente.
Nikesh K
Se você realmente espera objetos que não pertencem à classe "Pontuação", é necessário classificá-los com um pouco mais de cuidado. Caso contrário, você terá uma situação em que outros == score1 <score2 == other são inconsistentes e podem levar a problemas. Você pode retornar um valor que implique a classificação de objetos de pontuação antes de todos os outros objetos, e todos os outros objetos de classificação iguais um ao outro.
gnasher729
29

A partir do iOS 4, você também pode usar blocos para classificação.

Para este exemplo em particular, estou assumindo que os objetos em sua matriz tenham um método 'position', que retorna um NSInteger.

NSArray *arrayToSort = where ever you get the array from... ;
NSComparisonResult (^sortBlock)(id, id) = ^(id obj1, id obj2) 
{
    if ([obj1 position] > [obj2 position]) 
    { 
        return (NSComparisonResult)NSOrderedDescending;
    }
    if ([obj1 position] < [obj2 position]) 
    {
        return (NSComparisonResult)NSOrderedAscending;
    }
    return (NSComparisonResult)NSOrderedSame;
};
NSArray *sorted = [arrayToSort sortedArrayUsingComparator:sortBlock];

Nota: a matriz "classificada" será liberada automaticamente.

leviatã
fonte
26

Eu tentei tudo, mas isso funcionou para mim. Em uma classe, tenho outra classe chamada " crimeScene" e quero classificar por uma propriedade de " crimeScene".

Isso funciona como um encanto:

NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"crimeScene.distance" ascending:YES];
[self.arrAnnotations sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
Fernando Redondo
fonte
21

Falta um passo na segunda resposta de Georg Schölly , mas funciona bem então.

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                              ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];

// adicionou os 's' porque o tempo foi desperdiçado quando copiei e colei e ele falhou sem os 's' em SortArrayUsingDescriptors

Manuel Spuhler
fonte
A chamada do método é na verdade "classificadoArrayUsingDescriptors:", com um 's' no final.
CIFilter 13/05/09
19
NSSortDescriptor *sortDescriptor;
sortDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"birthDate" ascending:YES] autorelease];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingDescriptors:sortDescriptors];

Obrigado, está funcionando bem ...

Hardik Darji
fonte
17

Seus Personobjetos precisam implementar um método, dizer compare:qual pega outro Personobjeto e retornar de NSComparisonResultacordo com o relacionamento entre os dois objetos.

Então você ligaria sortedArrayUsingSelector:com@selector(compare:) e isso deve ser feito.

Existem outras maneiras, mas até onde eu sei, não existe equivalente de cacau na Comparableinterface. Usar sortedArrayUsingSelector:é provavelmente a maneira mais indolor de fazê-lo.

espaço livre
fonte
9

iOS 4 blocos irá salvar você :)

featuresArray = [[unsortedFeaturesArray sortedArrayUsingComparator: ^(id a, id b)  
{
    DMSeatFeature *first = ( DMSeatFeature* ) a;
    DMSeatFeature *second = ( DMSeatFeature* ) b;

    if ( first.quality == second.quality )
        return NSOrderedSame;
    else
    {
        if ( eSeatQualityGreen  == m_seatQuality || eSeatQualityYellowGreen == m_seatQuality || eSeatQualityDefault  == m_seatQuality )
        {
            if ( first.quality < second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        }
        else // eSeatQualityRed || eSeatQualityYellow
        {
            if ( first.quality > second.quality )
                return NSOrderedAscending;
            else
                return NSOrderedDescending;
        } 
    }
}] retain];

http://sokol8.blogspot.com/2011/04/sorting-nsarray-with-blocks.html um pouco de descrição

Kostiantyn Sokolinskyi
fonte
8

Para NSMutableArray, use o sortUsingSelectormétodo Ele classifica o local, sem criar uma nova instância.

DenTheMan
fonte
Apenas uma atualização: eu também estava procurando por algo que classificasse a matriz mutável, agora existem métodos equivalentes "sortUsing" para todos os métodos "sortArrayUsing" a partir do iOS 7. Tais como sortUsingComparator:.
jmathew
7

Você pode usar o seguinte método genérico para sua finalidade. Isso deve resolver seu problema.

//Called method
-(NSMutableArray*)sortArrayList:(NSMutableArray*)arrDeviceList filterKeyName:(NSString*)sortKeyName ascending:(BOOL)isAscending{
    NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:sortKeyName ascending:isAscending];
    [arrDeviceList sortUsingDescriptors:[NSArray arrayWithObject:sorter]];
    return arrDeviceList;
}

//Calling method
[self sortArrayList:arrSomeList filterKeyName:@"anything like date,name etc" ascending:YES];
MD Aslam Ansari
fonte
6

Se você estiver apenas classificando uma matriz de NSNumbers, poderá classificá-las com uma chamada:

[arrayToSort sortUsingSelector: @selector(compare:)];

Isso funciona porque os objetos na matriz ( NSNumberobjetos) implementam o método compare. Você pode fazer o mesmo por NSStringobjetos ou mesmo por uma matriz de objetos de dados personalizados que implementam um método de comparação.

Aqui está um exemplo de código usando blocos comparadores. Ele classifica uma matriz de dicionários em que cada dicionário inclui um número na chave "sort_key".

#define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
 ^(id obj1, id obj2) 
  {
  NSInteger value1 = [[obj1 objectForKey: SORT_KEY] intValue];
  NSInteger value2 = [[obj2 objectForKey: SORT_KEY] intValue];
  if (value1 > value2) 
{
  return (NSComparisonResult)NSOrderedDescending;
  }

  if (value1 < value2) 
{
  return (NSComparisonResult)NSOrderedAscending;
  }
    return (NSComparisonResult)NSOrderedSame;
 }];

O código acima passa pelo trabalho de obter um valor inteiro para cada chave de classificação e compará-los, como uma ilustração de como fazê-lo. Como os NSNumberobjetos implementam um método de comparação, ele pode ser reescrito de maneira muito mais simples:

 #define SORT_KEY @\"sort_key\"

[anArray sortUsingComparator: 
^(id obj1, id obj2) 
 {
  NSNumber* key1 = [obj1 objectForKey: SORT_KEY];
  NSNumber* key2 = [obj2 objectForKey: SORT_KEY];
  return [key1 compare: key2];
 }];

ou o corpo do comparador pode até ser destilado até uma linha:

  return [[obj1 objectForKey: SORT_KEY] compare: [obj2 objectForKey: SORT_KEY]];

Costumo preferir declarações simples e muitas variáveis ​​temporárias porque o código é mais fácil de ler e mais fácil de depurar. O compilador otimiza as variáveis ​​temporárias de qualquer maneira, portanto, não há vantagem na versão all-in-one-line.

Dinesh_
fonte
5

Eu criei uma pequena biblioteca de métodos de categoria, chamada Linq to ObjectiveC , que facilita esse tipo de coisa. Usando o método de classificação com um seletor de chave, você pode classificar da birthDateseguinte maneira:

NSArray* sortedByBirthDate = [input sort:^id(id person) {
    return [person birthDate];
}]
ColinE
fonte
Você deve chamá-lo de " LINQ to Objective-C ".
Peter Mortensen
5

Acabei de fazer a classificação em vários níveis com base nos requisitos personalizados.

// classifica os valores

    [arrItem sortUsingComparator:^NSComparisonResult (id a, id b){

    ItemDetail * itemA = (ItemDetail*)a;
    ItemDetail* itemB =(ItemDetail*)b;

    //item price are same
    if (itemA.m_price.m_selling== itemB.m_price.m_selling) {

        NSComparisonResult result=  [itemA.m_itemName compare:itemB.m_itemName];

        //if item names are same, then monogramminginfo has to come before the non monograme item
        if (result==NSOrderedSame) {

            if (itemA.m_monogrammingInfo) {
                return NSOrderedAscending;
            }else{
                return NSOrderedDescending;
            }
        }
        return result;
    }

    //asscending order
    return itemA.m_price.m_selling > itemB.m_price.m_selling;
}];

https://sites.google.com/site/greateindiaclub/mobil-apps/ios/multilevelsortinginiosobjectivec

Boobalan
fonte
5

Eu usei sortUsingFunction :: em alguns dos meus projetos:

int SortPlays(id a, id b, void* context)
{
    Play* p1 = a;
    Play* p2 = b;
    if (p1.score<p2.score) 
        return NSOrderedDescending;
    else if (p1.score>p2.score) 
        return NSOrderedAscending;
    return NSOrderedSame;
}

...
[validPlays sortUsingFunction:SortPlays context:nil];
roocell
fonte
5

Você usa o NSSortDescriptor para classificar um NSMutableArray com objetos personalizados

 NSSortDescriptor *sortingDescriptor;
 sortingDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                       ascending:YES];
 NSArray *sortArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];
Arvind Patel
fonte
4
-(NSMutableArray*) sortArray:(NSMutableArray *)toBeSorted 
{
  NSArray *sortedArray;
  sortedArray = [toBeSorted sortedArrayUsingComparator:^NSComparisonResult(id a, id b) 
  {
    return [a compare:b];
 }];
 return [sortedArray mutableCopy];
}
Emile Khattar
fonte
por que passar em uma matriz mutável, quando uma nova matriz é retornada. por que criar um wrapper?
vikingosegundo
3

A classificação NSMutableArrayé muito simples:

NSMutableArray *arrayToFilter =
     [[NSMutableArray arrayWithObjects:@"Photoshop",
                                       @"Flex",
                                       @"AIR",
                                       @"Flash",
                                       @"Acrobat", nil] autorelease];

NSMutableArray *productsToRemove = [[NSMutableArray array] autorelease];

for (NSString *products in arrayToFilter) {
    if (fliterText &&
        [products rangeOfString:fliterText
                        options:NSLiteralSearch|NSCaseInsensitiveSearch].length == 0)

        [productsToRemove addObject:products];
}
[arrayToFilter removeObjectsInArray:productsToRemove];
Mohit
fonte
2

Classificar usando o NSComparator

Se queremos classificar objetos personalizados, precisamos fornecer NSComparator, que é usado para comparar objetos personalizados. O bloco retorna um NSComparisonResultvalor para denotar a ordem dos dois objetos. Portanto, para classificar toda a matriz NSComparatoré usada da seguinte maneira.

NSArray *sortedArray = [employeesArray sortedArrayUsingComparator:^NSComparisonResult(Employee *e1, Employee *e2){
    return [e1.firstname compare:e2.firstname];    
}];

Classificações usando o NSSortDescriptor
Vamos supor, por exemplo, que temos uma matriz que contém instâncias de uma classe personalizada, Employee possui atributos nome, sobrenome e idade. O exemplo a seguir ilustra como criar um NSSortDescriptor que pode ser usado para classificar o conteúdo da matriz em ordem crescente pela chave de idade.

NSSortDescriptor *ageDescriptor = [[NSSortDescriptor alloc] initWithKey:@"age" ascending:YES];
NSArray *sortDescriptors = @[ageDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

Classificar usando comparações personalizadas Os
nomes são cadeias de caracteres e, quando você classifica as cadeias de caracteres para apresentar ao usuário, sempre deve usar uma comparação localizada. Geralmente, você também deseja realizar uma comparação sem distinção entre maiúsculas e minúsculas. A seguir, um exemplo com (localizedStandardCompare :) para ordenar a matriz pelo sobrenome e primeiro nome.

NSSortDescriptor *lastNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"lastName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSSortDescriptor * firstNameDescriptor = [[NSSortDescriptor alloc]
              initWithKey:@"firstName" ascending:YES selector:@selector(localizedStandardCompare:)];
NSArray *sortDescriptors = @[lastNameDescriptor, firstNameDescriptor];
NSArray *sortedArray = [employeesArray sortedArrayUsingDescriptors:sortDescriptors];

Para referência e discussão detalhada, consulte: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/SortDescriptors/Articles/Creating.html
http://www.ios-blog.co.uk/tutorials / object-c / como-ordenar-nsarray-com-objetos-personalizados /

Aamir
fonte
1

Os protocolos e a programação funcional do Swift tornam muito fácil você apenas tornar sua classe conforme o protocolo Comparável, implementar os métodos exigidos pelo protocolo e, em seguida, usar a função de ordem alta classificada (por:) para criar uma matriz classificada sem a necessidade de usar matrizes mutáveis ​​pelo caminho.

class Person: Comparable {
    var birthDate: NSDate?
    let name: String

    init(name: String) {
        self.name = name
    }

    static func ==(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate === rhs.birthDate || lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedSame
    }

    static func <(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedAscending
    }

    static func >(lhs: Person, rhs: Person) -> Bool {
        return lhs.birthDate?.compare(rhs.birthDate as! Date) == .orderedDescending
    }

}

let p1 = Person(name: "Sasha")
p1.birthDate = NSDate() 

let p2 = Person(name: "James")
p2.birthDate = NSDate()//he is older by miliseconds

if p1 == p2 {
    print("they are the same") //they are not
}

let persons = [p1, p2]

//sort the array based on who is older
let sortedPersons = persons.sorted(by: {$0 > $1})

//print sasha which is p1
print(persons.first?.name)
//print James which is the "older"
print(sortedPersons.first?.name)
James Rochabrun
fonte
1

No meu caso, eu uso "SortArrayUsingComparator" para classificar uma matriz. Veja o código abaixo.

contactArray = [[NSArray arrayWithArray:[contactSet allObjects]] sortedArrayUsingComparator:^NSComparisonResult(ContactListData *obj1, ContactListData *obj2) {
    NSString *obj1Str = [NSString stringWithFormat:@"%@ %@",obj1.contactName,obj1.contactSurname];
    NSString *obj2Str = [NSString stringWithFormat:@"%@ %@",obj2.contactName,obj2.contactSurname];
    return [obj1Str compare:obj2Str];
}];

Também meu objetivo é,

@interface ContactListData : JsonData
@property(nonatomic,strong) NSString * contactName;
@property(nonatomic,strong) NSString * contactSurname;
@property(nonatomic,strong) NSString * contactPhoneNumber;
@property(nonatomic) BOOL isSelected;
@end
Emre Gürses
fonte
1

É necessário criar sortDescriptor e, em seguida, você pode classificar o nsmutablearray usando o sortDescriptor como abaixo.

 let sortDescriptor = NSSortDescriptor(key: "birthDate", ascending: true, selector: #selector(NSString.compare(_:)))
 let array = NSMutableArray(array: self.aryExist.sortedArray(using: [sortDescriptor]))
 print(array)
Parth Barot
fonte
1

Use assim para objetos aninhados,

NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"lastRoute.to.lastname" ascending:YES selector:@selector(caseInsensitiveCompare:)];
NSMutableArray *sortedPackages = [[NSMutableArray alloc]initWithArray:[packages sortedArrayUsingDescriptors:@[sortDescriptor]]];

lastRoute é um objeto e esse objeto retém o objeto to, que o objeto retém os valores da string lastname.

Sureshkumar Linganathan
fonte
0

Classificar matriz em Swift


Para SwiftyPessoa abaixo, é uma técnica muito limpa para atingir acima da meta globalmente. Vamos ter um exemplo de classe personalizada Usercom alguns atributos.

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
}

Agora temos uma matriz que precisamos ordenar com base createdDateem ascendente e / ou descendente. Então, vamos adicionar uma função para comparação de datas.

class User: NSObject {
    var id: String?
    var name: String?
    var email: String?
    var createdDate: Date?
    func checkForOrder(_ otherUser: User, _ order: ComparisonResult) -> Bool {
        if let myCreatedDate = self.createdDate, let othersCreatedDate = otherUser.createdDate {
            //This line will compare both date with the order that has been passed.
            return myCreatedDate.compare(othersCreatedDate) == order
        }
        return false
    }
}

Agora vamos ter um extensionde Arraypara User. Em palavras simples, vamos adicionar alguns métodos apenas para aqueles que possuem apenas Userobjetos.

extension Array where Element: User {
    //This method only takes an order type. i.e ComparisonResult.orderedAscending
    func sortUserByDate(_ order: ComparisonResult) -> [User] {
        let sortedArray = self.sorted { (user1, user2) -> Bool in
            return user1.checkForOrder(user2, order)
        }
        return sortedArray
    }
}

Uso para ordem crescente

let sortedArray = someArray.sortUserByDate(.orderedAscending)

Uso para ordem decrescente

let sortedArray = someArray.sortUserByDate(.orderedAscending)

Uso para a mesma ordem

let sortedArray = someArray.sortUserByDate(.orderedSame)

O método acima em extensionsomente será acessível se o Arrayfor do tipo [User]||Array<User>

Syed Qamar Abbas
fonte
0

Versão Swift: 5.1

Se você possui uma estrutura ou classe personalizada e deseja classificá-las arbitrariamente, chame sort () usando um fechamento à direita que classifique em um campo especificado. Aqui está um exemplo usando uma matriz de estruturas personalizadas classificadas em uma propriedade específica:

    struct User {
        var firstName: String
    }

    var users = [
        User(firstName: "Jemima"),
        User(firstName: "Peter"),
        User(firstName: "David"),
        User(firstName: "Kelly"),
        User(firstName: "Isabella")
    ]

    users.sort {
        $0.firstName < $1.firstName
    }

Se você deseja retornar uma matriz classificada em vez de classificá-la no lugar, use classificado () assim:

    let sortedUsers = users.sorted {
        $0.firstName < $1.firstName
    }
sDev
fonte
0
  let sortedUsers = users.sorted {
    $0.firstName < $1.firstName
 }
manishkumar
fonte
A pergunta é sobre o NSMutableArray, não sobre a coleção Arrays no Swift
Ricardo
-2
NSMutableArray *stockHoldingCompanies = [NSMutableArray arrayWithObjects:fortune1stock,fortune2stock,fortune3stock,fortune4stock,fortune5stock,fortune6stock , nil];

NSSortDescriptor *sortOrder = [NSSortDescriptor sortDescriptorWithKey:@"companyName" ascending:NO];

[stockHoldingCompanies sortUsingDescriptors:[NSArray arrayWithObject:sortOrder]];

NSEnumerator *enumerator = [stockHoldingCompanies objectEnumerator];

ForeignStockHolding *stockHoldingCompany;

NSLog(@"Fortune 6 companies sorted by Company Name");

    while (stockHoldingCompany = [enumerator nextObject]) {
        NSLog(@"===============================");
        NSLog(@"CompanyName:%@",stockHoldingCompany.companyName);
        NSLog(@"Purchase Share Price:%.2f",stockHoldingCompany.purchaseSharePrice);
        NSLog(@"Current Share Price: %.2f",stockHoldingCompany.currentSharePrice);
        NSLog(@"Number of Shares: %i",stockHoldingCompany.numberOfShares);
        NSLog(@"Cost in Dollars: %.2f",[stockHoldingCompany costInDollars]);
        NSLog(@"Value in Dollars : %.2f",[stockHoldingCompany valueInDollars]);
    }
    NSLog(@"===============================");
Siddhesh Bondre
fonte