한국 연락처앱에선 없어서는 안될, '초성검색'을
'erica sudan'이라는 분이 만든,
ABContactHelper에 추가 구현해 보도록 하겠습니다.
ABContactHelper 프로젝트는 말그대로, iOS 의 AddressBook API 를 wrapping 해놓은것입니다.
AddressBook API 가 NS 쪽 이 아닌 CF 쪽 계열이다 보니, Memory 관리나 이런게 귀찮은 부분이 많은데, 그를 해소하고자 'Erica Sudan'이 Wrapping 해놓은 Library 입니다.
우선 코드를 다운 받고 아래와 같이 Test Case를 작성하였습니다.
#import "KoreanSearchTest.h"
#import "ABContactsHelper.h"
@interface KoreanSearchTest()
@property (nonatomic, retain) ABContact *contact;
@end
@implementation KoreanSearchTest
@synthesize contact = mContact;
- (void)setUp
{
[super setUp];
// Set-up code here.
ABContact *contact = [ABContact contact];
contact.firstname = @"긱보드";
[ABContactsHelper addContact:contact withError:NULL];
self.contact = contact;
}
- (void)tearDown
{
// Tear-down code here.
[self.contact removeSelfFromAddressBook:NULL];
self.contact = nil;
[super tearDown];
}
- (void)testExample
{
NSArray *contacts = [ABContactsHelper contactsMatchingName:@"긱보드"];
STAssertTrue([contacts count] > 0, @"");
contacts = [ABContactsHelper contactsMatchingName:@"ㄱㅂㄷ"];
STAssertTrue([contacts count] > 0, @"");
}
@end
* line 34 번의 Test 는 초성검색이 아닌 일반 검색으로 따로 코드를 수정하지 않아도 통과합니다.
* line 37 번의 Test가 초성검색을 확인하는 것으로 현재는 '당연히' 통과하지 않습니다.
Q. 초성검색을 어떻게 할것인가?
여러 지인들의 구현방법 + 인터넷 상의 얘기들을 보면, 보통 초성을 분리 해서 저장하는 하고,
초성으로 저장된 녀석을 검색하는 방법을 많이 씁니다.
초성 분리 코드는 'http://skyrack.tistory.com/118' 에서 소개된 코드를 사용하도록 하겠습니다.
1. 초성 property 선언
@property (nonatomic, readonly) NSString *contactName; // my friendly utility
@property (nonatomic, readonly) NSString *compositeName; // via AB
@property (nonatomic, retain) NSString *chosung; // Geekboard add
2. 초성 getter 구현
@synthesize chosung = mChosung;
- (NSString *)chosung {
if(mChosung == nil) {
NSString *contactName = [self contactName];
const NSArray *chosung = [NSArray arrayWithObjects:@"ㄱ",@"ㄲ",@"ㄴ",@"ㄷ",@"ㄸ",@"ㄹ",@"ㅁ",@"ㅂ",@"ㅃ",@"ㅅ",@"ㅆ",@"ㅇ",@"ㅈ",@"ㅉ",@"ㅊ",@"ㅋ",@"ㅌ",@"ㅍ",@"ㅎ",nil];
NSString *textResult = @"";
for (int i=0;i<[contactName length];i++) {
NSInteger code = [contactName characterAtIndex:i];
if (code >= 44032 && code <= 55203) {
NSInteger uniCode = code - 44032;
NSInteger chosungIndex = uniCode / 21 / 28;
textResult = [textResult stringByAppendingFormat:[chosung objectAtIndex:chosungIndex]];
}
else {
textResult = [textResult stringByAppendingFormat:@"%C", code];
}
}
if([contactName isEqualToString:textResult] == YES) {
mChosung = [[NSString alloc] initWithString:@""];
}
else {
mChosung = [[NSString alloc] initWithString:textResult];
}
}
return mChosung;
}
3. contactsMatchingName: method 수정
+ (NSArray *) contactsMatchingName: (NSString *) fname
{
NSPredicate *pred;
NSArray *contacts = [ABContactsHelper contacts];
// Geekboard : 'chosung' key 도 검색하도록 수정
pred = [NSPredicate predicateWithFormat:@"chosung contains[cd] %@ OR firstname contains[cd] %@ OR lastname contains[cd] %@ OR nickname contains[cd] %@ OR middlename contains[cd] %@ ", fname, fname, fname, fname,fname];
return [contacts filteredArrayUsingPredicate:pred];
}
Q. 이게 끝일까요?
- (void)testExample
{
contacts = [ABContactsHelper contactsMatchingName:@"긱ㅂㄷ"];
STAssertTrue([contacts count] > 0, @"");
}
현재 상태로는 위의 Test 를 통과하지 못합니다. ( 초성 + 일반 글자 혼용 형태)
제가 작성한 소스는 아래의 링크로 공유되어 있으니,
https://github.com/Geekboard/ABContactHelper
한번 해결해보시는건 어떨까요? :)