[objective-c] compare.
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이라는 클래스를 하나 정의했을 때..
#import | |
@interface Person : NSObject | |
@property (strong, nonatomic) NSString *name; | |
-(NSComparisonResult)compare:(Person *)otherPerson; | |
@end |
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 |
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); | |
} |
만약, 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); | |
} |
돌아간다... ㅋ
자바처럼 꼭 같은 인터페이스여야만하는.. 그런 제약은 없는 것 같다. 주로 메서드의 시그너쳐를 중심으로 돌아갈 수 있는 구조인듯하다. 그래서 공식/비공식 프로토콜도 나누어져있고.. 카테고리라는 기법도 가능한듯..