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
56 Apple AppStore App Review 시 Reject 피하기 위한 방법 digipine 2017.11.02 629
55 Concurrent vs Serial DispatchQueue: Concurrency in Swift explained lizard2019 2021.04.16 671
54 Core Audio를 사용하여 macOS에서 Audio를 Capture하는 코드 digipine 2024.04.19 462
53 Firebase 'GoogleUtilities/GULURLSessionDataResponse.h' file not found Error Fix lizard2019 2023.07.04 635
52 iOS , MacOS, iPhone용 GZipStream class 구현하기 digipine 2017.11.01 690
51 iOS - BLE 장치용 ANCS Library for ANCS digipine 2017.11.02 1119
50 iOS - BSD Socket 네트워크 프로그래밍 digipine 2017.11.01 946
49 iOS - NSString 와 NSData 간의 데이터 상호 변환 digipine 2017.11.01 538
48 iOS - NSString의 언어 인코딩 메소드 정리 digipine 2017.11.01 1036
47 iOS - NSURLConnection로 다중 다운로드 구현 digipine 2017.11.01 630
46 iOS - Objective - C 정규식 사용하기 digipine 2017.11.01 926
45 iOS - Objective - C, URL 인코딩과 디코딩 digipine 2017.11.01 2244
44 iOS - Objective C 정규식 사용법 2 digipine 2017.11.01 1404
43 iOS - Objective-C Callback for C++ digipine 2017.11.01 579
42 iOS - Objective-C 남아있는 메모리 공간 확인 방법 digipine 2017.11.01 495
41 iOS - Openssl 빌드하기 digipine 2017.11.01 1280
40 iOS - OpenURL으로 HTML에서 어플 실행 digipine 2017.11.01 892
39 iOS - Query string을 Decode 하는 소스 digipine 2017.11.01 651
38 iOS - sizeWithFont 메소드 deprecated와 sizeWithAttributes digipine 2017.11.02 902
37 iOS - Sleep Mode Blocking 방법, 앱실행시 슬립모드 진입 방지 digipine 2017.11.01 906
Board Pagination Prev 1 2 3 Next
/ 3