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
55 macOS Daemon 관련 시스템 폴더 목록 lizard2019 2024.03.08 23
54 [macOS, iOS] 개발자 정보 확인하는 명령어 digipine 2023.03.23 161
53 iOS - Socket Nagle 알고리듬 OFF digipine 2017.11.01 208
52 Firebase 'GoogleUtilities/GULURLSessionDataResponse.h' file not found Error Fix lizard2019 2023.07.04 210
51 iOS - Thread Loop 내에서 UI 업데이트 방법 digipine 2017.11.01 211
50 iOS - Objective-C 남아있는 메모리 공간 확인 방법 digipine 2017.11.01 215
49 iOS - NSString 와 NSData 간의 데이터 상호 변환 digipine 2017.11.01 249
48 iOS - Objective-C Callback for C++ digipine 2017.11.01 266
47 [macOS] 현재 사용 중인(열려있는) 포트 확인하고 Close 하기 digipine 2022.10.24 269
46 iOS - Query string을 Decode 하는 소스 digipine 2017.11.01 327
45 iOS - NSURLConnection로 다중 다운로드 구현 digipine 2017.11.01 333
44 iOS , MacOS, iPhone용 GZipStream class 구현하기 digipine 2017.11.01 358
43 Concurrent vs Serial DispatchQueue: Concurrency in Swift explained lizard2019 2021.04.16 415
42 iOS,OSX - CFSocket 사용법 digipine 2017.11.01 444
41 Apple AppStore App Review 시 Reject 피하기 위한 방법 digipine 2017.11.02 447
40 iOS - Objective - C 정규식 사용하기 digipine 2017.11.01 470
39 [iOS] 개발자를 위한 iOS 15의 새로운 기능 file digipine 2021.11.04 498
38 iOS - View 이동 전환 하기 총정리 digipine 2017.11.01 537
37 [iOS] Audio Session Setting digipine 2021.11.26 548
36 [macOS] Xcode 디버깅 시 Could not attach pid 오류 해결 file lizard2019 2023.06.05 561
Board Pagination Prev 1 2 3 Next
/ 3