Swft의 Array는 간단한 방법으로 정렬할 수 있지만, Objecitve-C의 배열인 NSArray
는 정렬하는 것이 그리 간단치가 않다. 배열을 정렬하기 위해서는 어떤 알고리듬을 사용하는지와 무관하게 기본적으로 두 개의 요소 중에서 어느 것이 앞으로 가야할지, 비교할 수 있는 기준이 필요하다. 두 요소가 특정 기준에 대해 동일한 값을 같는다면 두 번째로 적용되어야 할 기준을 사용하는 경우도 있다.
코코아에서는 NSSortDescriptor
라는 클래스를 사용하여 배열(다른 집합형 컨테이너도 해당) 내의 원소들을 정렬할 수 있다. 이 디스크립터를 사용해서 정렬 기준을 만들고 정렬하는 메소드에 파라미터로 전달한다. 단, 이러한 방식은 매우 오래전의 방식이며, Objecitve-C 2.0에서 코드 블럭에 대한 지원이 강화된 뒤로는 코드 블럭이나 함수, 메소드를 사용하여 정렬하는 방식이 더 널리 쓰인다.
참고로 NSArray
는 변경이 불가능한 immutable한 타입이다. 이러한 타입들은 정렬 시 sortedArray~*
와 같은 식으로 정렬된 사본을 만든다. NSMuatbleArray
는 내부 변경이 가능하므로, -sortWith*:
와 같은 메소드도 사용할 수 있다.
정렬 디스크립터
정렬 디스크립터는 어떤 배열/집합 내 원소들에서 그 중 어떤 속성을 사용하여 순서를 정할 것인지를 정의하는 객체이다. 따라서 비교에 사용할 기준이 되는 프로퍼티 이름을 키로 사용하여 간단하게 생성할 수 있다.
하지만 어떤 경우에는 프로퍼티 자체로 비교가 곤란하거나, 별도의 로직으로 비교하고 싶은 경우도 있다. 대소문자를 구분하지 않는 문자열 비교나, 문자열의 길이 순서대로 정렬하는 등 별도의 로직을 이용하려는 경우에는 코드 블럭을 사용하여 비교하는 디스크립터를 만들면된다.
NSSortDescriptor *ageDescriptor = [NSSortDescriptor descriptorWithKey:@"age"
ascending:YES];
NSSortDescriptor *hireDateDescriptor = [NSSortDescriptor
descriptorWithKey:@"hireDate"
asceding:NO];
NSArray *sortedEmployees = [employeesArray sortedArrayUsingDescriptors:
@[ageDescriptor, hireDateDescriptor]];
블럭을 사용하여 정렬하기
-sortedArrayUsingComparator:
를 사용하면 디스크립터 대신에 별도의 코드 블럭을 사용하여 배열을 정렬할 수 있다. 이 때 사용되는 코드 블럭은 ^(NSComparisonResult)(id, id)
타입으로 두 개의 객체를 인자로 받고 NSComparisonResult
타입의 값을 리턴한다. 이 값은 앞쪽 인자의 객체가 더 낮은 우선순위인지 높은 순위인지 혹은 같은지를 뜻하는 값으로 다음과 같은 상수로 정의되어 있다.
NSOrderedDescending
NSOrderedAscending
NSOrderedSame
NSArray *sortedEmployees = [employeesArray sortedArrayUsingComparator:^(id obj1, id obj2){
if (obj1.age < obj2.age) return NSOrderedAscending;
if (obj1.age > obj2.age) return NSOrderedDescending;
if ([obj1.hireDate compare:obj2.hireDate] == NSOrderedAscending) {
return NSOrderedDescending;
} else { return NSOrderedDescending }
}];
커스텀 집합을 정렬하기 위한 조건
정렬 디스크립터는 -compareObject:toObject:
메소드를 지원하며, 이를 사용하여 두 객체의 우선순위를 비교할 수 있다. 이를 이용하면 커스텀 집합 클래스의 정렬을 직접 구현할 수 있다. 이 때 정렬 디스크립터는 실제로 비교할 값에 접근하기 위해 비교 대상인 두 객체에 대해서 키-밸류 코딩을 사용하여 프로퍼티에 접근한다. 따라서 집합의 원소가 되는 객체들은 기본적으로 키-밸류 코딩에 호환되는 방식으로 작성되어 있어야 한다.