logo

English

이곳의 프로그래밍관련 정보와 소스는 마음대로 활용하셔도 좋습니다. 다만 쓰시기 전에 통보 정도는 해주시는 것이 예의 일것 같습니다. 질문이나 오류 수정은 siseong@gmail.com 으로 주세요. 감사합니다.

[iOS, MacOS] NSArray 정렬 Sorting에 대해서

by digipine posted Nov 02, 2017
?

Shortcut

PrevPrev Article

NextNext Article

Larger Font Smaller Font Up Down Go comment Print
?

Shortcut

PrevPrev Article

NextNext Article

Larger Font Smaller Font Up Down Go comment Print

배열을 정리하는 방식은 크게 세 가지로 1)디스크립터를 사용하거나 2)블럭, 3)셀렉터를 사용하는 방법이 있다. 각각이 표현의 차이는 있는데 실제로는 각 요소들을 비교하여 어떤 것이 앞에 오는지를 비교하여 정렬하게 된다.

 

1. sort descriptor를 사용하는 법

 

디스크립터는 NSSortDescriptor의 인스턴스로, 정렬 순서를 표현하는 클래스이다. 코어데이터의 fetch 동작에도 사용되는데, 상당히 간단하고 코코아 바인딩에도 적용할 수 있는 등, 활용 범위가 넓다. 디스크립터를 사용한 정렬은 배열 객체에 sortedArrayUsingDescriptors: 나 sortUsingDescriptors: 메시지를 보내서 적용할 수 있다.

 

이 과정은 다음과 같이 구현한다.

 

NSSortDescriptor 객체를 만든다. 이 객체를 만들 때는 비교의 대상이 되는 키이름과 정렬순서(오름차순인지 내림차순인지) 및 비교에 사용할 메소드를 지정한다.

만약 두 가지 이상의 기준을 사용한다면 디스크립터를 필요한 만큼 만든다.

디스크립터들을 하나의 배열 객체로 만든다.

정렬할 배열 객체에 sortedArrayUsingDescriptors: 메시지를 보내어 정렬된 배열 사본을 얻을 수 있다.

예를 들어 firstName, lastName의 두 개 키로 구성된 사전에 사람의 이름을 넣고, 이 사전들로 구성된 배열을 정렬하는 케이스를 살펴보겠다.

 

NSString *LAST = @"lastName";

NSString *FIRST = @"firstName";

NSMutableArray *array = [NSMutableArray array];

NSArray *sortedArray;

NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:

                        @"Jo",FIRST,@"Smith",LAST,nil];

[array addObject:dict];

/**....**/

//위 과정을 반복하여 충분한 수의 사람 이름을 배열에 추가함

 

NSSortDescriptor *lastNameDescriptor = [[NSSortDescriptor alloc]

                                          initWithKey:LAST

                                           ascending:YES

                                            selector:@selector(localizedCaseInsensitiveCompare:)];

NSSortDescriptor *firstNameDescriptor = [[NSSortDescriptor alloc]

                          initWithKey:FIRST

                            ascending:YES

                             selector:@selector(localizedCaseInsensitiveCompare:)];

NSArray *descriptors = [NSArray arrayWithObjects:lastDescriptor, firstDescriptor, nil];

sortedArray = [array sortedArrayUsingDescriptors:descriptors];

 

 

여기서 디스크립터 배열의 원소의 순서는 비교의 우선순위가 된다. 즉 lastname으로 정렬하고, 같은 lastname인 경우에는 firstname으로 다시 정렬하게 된다. 문자열을 비교하고 있으므로 디스크립터를 만들때 localizedCaseInsensitiveCompare: 메소드를 사용했다.

 

2. 블럭코딩으로 정렬하기

 

요건은 간단하다. 디스크립터의 compare: 메소드를 블럭으로 구현하는 것이다. 두 개의 값을 비교해서 뒤에 오는 값이 크거나 뒤의 것이라면 NSOrderedDescending을, 반대라면 NSOrderAscending을, 같다면 NSOrderSame을 내놓으면 된다. 이 원리를 사용하면 블럭으로 소팅하는 것으로 두 개 숫자값 (배열에 들어있으므로 NSNumber가 되어있을)을 비교할 수 있다.

 

NSArray *sortedArray = [array sortedArrayUsingComparator:^(id obj1, id obj2) {

      if ([obj1 integerValue] > [obj2 integerValue])

          return (NSComparisonResult)NSOrderDescending;

      else if ([obj1 integerValue] < [obj2 integerValue] )

          return (NSComparisonResult)NSOrderAscending;

      else

           return (NSComparisonResult)NSOrderSame;

 

}];

 

3. Sort Descriptor 추가 내용

 

정렬 디스크립터는 정렬기준을 표현하는 클래스라고 했다. 처음 예제 코드에서는 셀렉터를 사용하도록 했는데, 만일 해당 키가 문자열이 아니라면 셀렉터를 사용하지 않아도 된다. 만약 NSNumber로 된 키를 사용한다고 하면 다음과 같이 사용하면 된다.

 

NSSortDescriptor *ageDescriptor = [[NSSortDescriptor alloc]

                    initWithKey:@"age" ascending:YES];

NSArray *sortDescriptors = [NSArray arrayWithObject:ageDescriptor];

sortedArray = [studentsArray sortedArrayUsingDescriptors:sortDescriptors];

 

위 예제는 정렬 디스크립터를 만들면서 별도로 비교방법을 주지 않았다. 이 경우에는 디폴트 비교 메소드인 compare:가 사용된다. 이 메소드는 NSNumber와 NSDate 등에 쓰인다. 만약 문자열을 비교한다면 NSString이 가지고 있는 비교 메소드를 사용해야 한다. 문자열이 사용자에게 보여진다면 비교시에는 localizedCompare: / localizedCaseInsensitiveCompare:를 사용해야 한다.

 

 

비교를 위한 메소드는 위의 블럭을 사용한 예에서 살펴보았듯이, 특정 객체에게 메시지를 보내서, 인자로 넘긴 객체와의 순서가 앞이냐, 뒤냐를 판별하게 하는 것이다. 만약 임의의 객체를 정렬해야 한다면 해당 객체에 비교를 위한 메소드를 구현해두거나, 카테고리를 사용하여 추가해서 사용하는 방법을 쓸 수도 있을 것이다.

 
TAG •

List of Articles
No. Subject Author Date Views
36 [MacOS] Terminal 에서 zsh compinit: insecure directories 경고 제거하기 lizard2019 2021.04.30 567
35 iOS - OpenURL으로 HTML에서 어플 실행 digipine 2017.11.01 570
34 [iOS, MacOS] ATS 보안 정책 가이드 digipine 2017.11.02 571
33 iOS - Sleep Mode Blocking 방법, 앱실행시 슬립모드 진입 방지 digipine 2017.11.01 573
32 iOS - sizeWithFont 메소드 deprecated와 sizeWithAttributes digipine 2017.11.02 611
31 [macOS] Xcode 디버깅 시 Could not attach pid 오류 해결 file lizard2019 2023.06.05 635
30 iOS - UILabel 에서 AttributeString 사용하기 digipine 2017.11.02 640
29 iOS - BSD Socket 네트워크 프로그래밍 digipine 2017.11.01 665
» [iOS, MacOS] NSArray 정렬 Sorting에 대해서 digipine 2017.11.02 668
27 The distance estimate iBeacon signal strength lizard2019 2019.10.25 696
26 macOS ARP Spoofing Attack file digipine 2020.09.17 699
25 XCode 8 업데이트 후 Code Sign Error 발생 시 해결법 1 digipine 2017.11.02 713
24 iOS - NSString의 언어 인코딩 메소드 정리 digipine 2017.11.01 717
23 WatermelonDB 'jsi/jsi.h' file not found 문제 해결 file digipine 2021.04.06 734
22 OpenAL PDF, Sample Source file digipine 2017.11.02 796
21 iOS - 코드 수행시간 측정하기 - getTickCount digipine 2017.11.01 848
20 iOS - Openssl 빌드하기 digipine 2017.11.01 947
19 iOS - BLE 장치용 ANCS Library for ANCS digipine 2017.11.02 950
18 iOS - Objective C 정규식 사용법 2 digipine 2017.11.01 968
17 [swift 4] 변경 사항 정리 file 엉뚱도마뱀 2018.07.23 1020
Board Pagination Prev 1 2 3 Next
/ 3