ios - transformar - toque da apple download




Como faço para classificar um NSMutableArray com objetos personalizados nele? (17)

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 melhor ainda:

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 ao array. Também é possível usar métodos de comparação 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

Os métodos -compare: e block-based serão um pouco mais rápidos, em geral, do que usar o NSSortDescriptor pois o último depende do KVC. A principal vantagem do método NSSortDescriptor é que ele fornece uma maneira de definir sua ordem de classificação usando dados, em vez de código, o que torna fácil, por exemplo, configurar coisas para que os usuários possam classificar um NSTableView clicando na linha de cabeçalho.

O que eu quero fazer parece bastante simples, mas não consigo encontrar nenhuma resposta na web. Eu tenho um NSMutableArray de objetos e digamos que eles são objetos 'Person'. Eu quero classificar o NSMutableArray por Person.birthDate que é um NSDate .

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

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

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


Ordenar Array Em Swift

Para Swifty Person abaixo está uma técnica muito limpa para alcançar o objetivo acima para globalmente. Vamos ter um exemplo de classe customizada de User que possui alguns atributos.

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

Agora temos um array que precisamos classificar com base em createdDate ascendente e / ou decrescente. 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 uma extension de Array for User . Em palavras simples, vamos adicionar alguns métodos apenas para aqueles Array que só possuem objetos User nele.

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 Ascendente

let sortedArray = someArray.sortUserByDate(.orderedAscending)

Uso para ordem decrescente

let sortedArray = someArray.sortUserByDate(.orderedAscending)

Uso para o mesmo pedido

let sortedArray = someArray.sortUserByDate(.orderedSame)

O método acima na extension só será acessível se o Array for do tipo [User] || Array<User>


Acabei de fazer uma classificação de vários níveis com base em 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


Blocos do iOS 4 vão te salvar :)

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


Eu fiz isso no iOS 4 usando um bloco. Tive que converter os elementos da minha matriz de 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 de sua matriz não forem do tipo certo. Para este exemplo, acabei de retornar NSOrderedSame , no entanto, em meu código, apesar de 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: Isso está classificando em ordem decrescente.


Eu tentei de tudo, mas isso funcionou para mim. Em uma classe eu 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]];

Há um passo em falta 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 sortedArrayUsingDescriptor:sortDescriptors];

No meu caso, eu uso "sortedArrayUsingComparator" 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

Os protocolos e programação funcional do Swift tornam isso muito fácil. Basta fazer com que sua classe esteja em conformidade com o protocolo Comparable, implementar os métodos exigidos pelo protocolo e usar a função ordenada ordenada (por:) para criar um array ordenado sem precisar 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)

Para NSMutableArray , use o método sortUsingSelector . Ele classifica o lugar, sem criar uma nova instância.


Seus objetos Person precisam implementar um método, digamos compare: que leva outro objeto Person e retorna NSComparisonResult acordo com o relacionamento entre os dois objetos.

Em seguida, você chamaria sortedArrayUsingSelector: com @selector(compare:) e isso deve ser feito.

Existem outras maneiras, mas, até onde sei, não há cacau-equiv da interface Comparable . Usando sortedArrayUsingSelector: é provavelmente a maneira mais indolor de fazer isso.


Veja o método NSMutableArray sortUsingFunction:context:

Você precisará configurar uma função de comparação que obtenha dois objetos (do tipo Person , já que você está comparando dois objetos Person ) 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 NSOrderedAscending se PersonA.birthDate < PersonB.birthDate . Ele retornará NSOrderedDescending se PersonA.birthDate > PersonB.birthDate . Finalmente, retornará NSOrderedSame se PersonA.birthDate == PersonB.birthDate .

Este é um pseudocódigo áspero; você precisará detalhar o que significa para uma data ser "menos", "mais" ou "igual" a outra data (como comparar segundos-desde-epoch 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ê quer algo mais compacto, você pode 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 poderia talvez acelerar um pouco, se você fizer isso muito.


Você tem que criar sortDescriptor e então você pode classificar o nsmutablearray usando 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)

Você usa NSSortDescriptor para classificar um NSMutableArray com objetos personalizados

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

-(NSMutableArray*) sortArray:(NSMutableArray *)toBeSorted 
{
  NSArray *sortedArray;
  sortedArray = [toBeSorted sortedArrayUsingComparator:^NSComparisonResult(id a, id b) 
  {
    return [a compare:b];
 }];
 return [sortedArray mutableCopy];
}

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(@"===============================");

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 ...





nsmutablearray