Objective-C

[objective-c] compare.

용식 2012. 8. 27. 22:33

NSDictionary의 정렬 메소드 중 keysSortedByValueUsingSelector:(SEL)selector 가 있다.

NSDictionary의 value로 키값을 정렬하는 메소드이다.


역시나.. 자바에만 익숙해져있는 나는..

이 상황이 이해가 안된다. ㅋㅋ 아니 뭐 NSDictionary가 정렬 메서드를 가지고 있으면 되는거지

저기다가 Selector를 던지는건 당최 뭐람...



NSDictionary *ndic = [[NSDictionary alloc] initWithObjectsAndKeys:@"value1", @"key1", @"value2", @"key2", nil];
NSLog(@"ndic %@", [ndic objectForKey:@"key1"]);
for(NSString *key in ndic) {
NSLog(@"%@", key);
}
NSArray *keySorted = [ndic keysSortedByValueUsingSelector:@selector(compare:)];
for(NSString *key in keySorted) {
NSLog(@"%@", key);
}


이런것인데... 바로 keysSortedByValueUsingSelector:@selector(compare:).. 이 부분이

처음 이해가 안 되었던 부분.. Java랑 비교하면.. Map으로 들어가는 객체가 Comparable 인터페이스를 구현한 것과..

비슷하다고 보면 될듯하다.


실제로 위 메서드가 호출되면 NSDictionary의 value로 들어가 있는 객체에 구현되어 있는 compare 메서드를

실행한다. 위와 같은 경우는 NSString에 구현되어있는 (오버라이드 되어있는) compare가 사용되는것 같다.

모르긴 몰라도 그 selector 자체를 value로 들어가 있는 객체에 던져서 실행을 하겠지..

(엄격히 얘기하면.. -(NSComparisonResult)compare:(NSString *)otherString;이 되겠다.)


예를들어서 Person이라는 클래스를 하나 정의했을 때..


Person.h
#import
@interface Person : NSObject
@property (strong, nonatomic) NSString *name;
-(NSComparisonResult)compare:(Person *)otherPerson;
@end
view raw person.h hosted with ❤ by GitHub

Person.m
#import "Person.h"
@implementation Person
@synthesize name;
-(NSComparisonResult)compare:(Person *)otherPerson {
NSComparisonResult comp_result = [self.name compare:otherPerson.name];
return comp_result;
}
@end
view raw person.m hosted with ❤ by GitHub

main.m
Person *a = [[Person alloc] init];
[a setName:@"jang"];
Person *b = [[Person alloc] init];
[b setName:@"an"];
NSDictionary *personDic = [[NSDictionary alloc] initWithObjectsAndKeys:a, @"a", b, @"b", nil];
NSArray *personSort = [personDic keysSortedByValueUsingSelector:@selector(compare:)];
for(NSString *person in personSort) {
NSLog(@"%@", person);
}
view raw main.m hosted with ❤ by GitHub

만약, Person.m에 compare 메서드가 구현이 안되어있다고 하면,.

위 실행코드는 런타임에 에러가 발생한다.


Person을 비교 할 메서드가 없기 때문.. (여기서는 compare)


그렇다면... 혹시 메서드의 이름이 굳이 compare가 아니어도 되지 않을까? 그냥 NSComparisonResult가 리턴하는 메서드면

되지 않을까.. 라는 생각이 들어서.... 즉흥적으로 테스트를..


Person에 아래와 같은 메서드를 선언 및 구현하고..


//in Person.h
-(NSComparisonResult)customCompare:(Person *)otherPerson;
//in Person.m
-(NSComparisonResult)customCompare:(Person *)otherPerson {
NSComparisonResult comp_result = [self.name compare:otherPerson.name];
return comp_result;
}
// in main
NSDictionary *personDic = [[NSDictionary alloc] initWithObjectsAndKeys:a, @"a", b, @"b", nil];
//NSArray *personSort = [personDic keysSortedByValueUsingSelector:@selector(compare:)];
NSArray *personSort = [personDic keysSortedByValueUsingSelector:@selector(customCompare:)];
for(NSString *person in personSort) {
NSLog(@"%@", person);
}
view raw usage.m hosted with ❤ by GitHub


돌아간다... ㅋ

자바처럼 꼭 같은 인터페이스여야만하는.. 그런 제약은 없는 것 같다. 주로 메서드의 시그너쳐를 중심으로 돌아갈 수 있는 구조인듯하다. 그래서 공식/비공식 프로토콜도 나누어져있고.. 카테고리라는 기법도 가능한듯..