[ios] NSMutableArray를 커스텀 객체로 어떻게 정렬합니까?

내가하고 싶은 것은 매우 간단 해 보이지만 웹에서 답을 찾을 수 없습니다. 나는이 NSMutableArray오브젝트를, 그리고의 그들이 ‘사람’개체입니다 가정 해 봅시다. NSMutableArrayPerson.birthDate 로 정렬하고 싶습니다 NSDate.

이 방법과 관련이 있다고 생각합니다.

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

Java에서 객체를 Comparable로 구현하거나 인라인 사용자 정의 비교기와 함께 Collections.sort를 사용합니다 … 어떻게 Objective-C 에서이 작업을 수행합니까?



답변

방법 비교

객체에 대해 비교 방법을 구현하십시오.

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

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

NSSortDescriptor (더 나은)

또는 일반적으로 더 나은 :

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

배열에 둘 이상을 추가하여 여러 키로 쉽게 정렬 할 수 있습니다. 맞춤형 비교기 방법을 사용할 수도 있습니다. 설명서를 살펴보십시오 .

블록 (반짝!)

Mac OS X 10.6 및 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];
}];

공연

-compare:블록 기반 방법은 사용하지 않고, 상당히 빠른 일반적 것이다 NSSortDescriptor후자 KVC에 의존한다. 이 NSSortDescriptor방법 의 주요 장점은 코드가 아닌 데이터를 사용하여 정렬 순서를 정의 할 수있는 방법을 제공하므로 사용자가 NSTableView헤더 행을 클릭하여 정렬 할 수 있도록 설정 등을 쉽게 할 수 있다는 것 입니다.


답변

NSMutableArray방법을 참조하십시오sortUsingFunction:context:

두 개의 객체 ( 두 개의 객체를 비교하고 있기 때문에 유형 )와 컨텍스트 매개 변수 를 취하는 비교 함수 를 설정해야합니다 .PersonPerson

두 개체는 단지 인스턴스입니다 Person. 세 번째 객체는 문자열입니다 (예 : @ “birthDate”).

이 함수는 NSComparisonResult다음을 반환 NSOrderedAscending합니다 . PersonA.birthDate< 이면 반환 합니다 PersonB.birthDate. > NSOrderedDescending이면 반환 됩니다 . 마지막으로 == 이면 반환 합니다 .PersonA.birthDatePersonB.birthDateNSOrderedSamePersonA.birthDatePersonB.birthDate

이것은 거친 의사 코드입니다. 한 날짜가 다른 날짜와 “더 적다”, “더 많음”또는 “같다”는 의미 (예 : 초-에포크 등 비교)를 살살 빼야합니다.

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;
}

더 컴팩트 한 것을 원하면 삼항 연산자를 사용할 수 있습니다.

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

이 작업을 많이하면 인라이닝이 속도를 약간 높일 수 있습니다.


답변

iOS 4에서 블록을 사용 하여이 작업을 수행했습니다. 배열의 요소를 id에서 클래스 유형으로 캐스팅해야했습니다. 이 경우 점수라는 속성이있는 점수라는 클래스입니다.

또한 배열의 요소가 올바른 유형이 아닌 경우 수행 할 작업을 결정해야합니다.이 예제에서는 방금 반환 NSOrderedSame했지만 코드에서는 예외이지만 예외입니다.

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;

추신 : 이것은 내림차순으로 정렬됩니다.


답변

iOS 4부터는 정렬을 위해 블록을 사용할 수도 있습니다.

이 특정 예제에서는 배열의 객체에 ‘position’메서드가 있다고 가정합니다 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];

참고 : “정렬 된”배열은 자동 해제됩니다.


답변

나는 모든 것을 시도했지만 이것은 나를 위해 일했다. 클래스에 ” crimeScene“(이) 라는 또 다른 클래스가 있으며 ” “의 속성으로 정렬하려고합니다 crimeScene.

이것은 매력처럼 작동합니다.

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


답변

Georg Schölly의 두 번째 대답 에는 빠진 단계가 있지만 제대로 작동합니다.

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

// 복사하여 붙여 넣을 때 시간이 낭비되고 sortedArrayUsingDescriptors에서 ‘s’없이 실패했기 때문에 ‘s’를 추가했습니다.


답변

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

고마워요, 잘 작동합니다 …