iOSで連絡先からPersonレコードを取得する際に、名前のキーワードで検索して意図しない挙動となった。やりたかったのは名字の頭文字で検索して該当する名前を取得したかったのだが、これまでの処理では検索対象が名字だけでなく名前にもなっていたため、名字だけを検索対象となるように修正した。
Personレコードを検索する方法は以下の3つの方法がある。
- 1. 名前で検索する(ABAddressBookCopyPeopleWithName関数)
- 2. レコードIDで検索する(ABAddressBookGetPersonWithRecordID関数)
- 3. 検索結果をフィルタリングする(filteredArrayUsingPredicate関数)
これまでは1)のABAddressBookCopyPeopleWithNameを使用していたが、これは「姓」「姓(読み)」「名」「名(読み)」が検索対象(※日本語設定の場合)となり、これら全ての項目を検索対象とするある場合は便利だが、検索対象を1つに絞りたい場合などは不便だ。
ABAddressBookCopyPeopleWithNameでの検索
まずはABAddressBookRefを取得
- (ABAddressBookRef)createAddressBook {
ABAddressBookRef addressBook = NULL;
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0f) {
NSLog(@"iOS6以降の処理");
addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
}else{
NSLog(@"iOS6以前の処理");
addressBook = ABAddressBookCreate();
}
return addressBook;
}
「さ」で検索
- (void)searchNameAddress
{
NSString *keyword = @"さ";
NSArray * result = (__bridge NSArray *)(ABAddressBookCopyPeopleWithName([self createAddressBook], (__bridge_retained CFStringRef)keyword));
}
この結果は「姓」「名」「姓(読み)」「名(読み)」のどれかが「さ」から始まる場合に結果として返ってくる。
カタカナの場合でもヒットする。filteredArrayUsingPredicateでの検索
全てのPersonレコードを取得したあとに、「NSPredicate」にて条件を指定してデータをフィルタリングする
- (NSArray *)allPepole
{
ABAddressBookRef addressBook = [self createAddressBook];
NSArray *people = (NSArray *)CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
return people;
}
- (void)searchAddress
{
// 全データ取得
NSArray *pepole = [self allPepole];
NSArray *result = [pepole filteredArrayUsingPredicate:[NSPredicate predicateWithBlock: ^(id record, NSDictionary* bindings) {
ABRecordRef lastName = ABRecordCopyValue((__bridge ABRecordRef)record, kABPersonLastNamePhoneticProperty);
NSString *lname = (__bridge_transfer NSString*)lastName;
return [lname hasPrefix:@"さ"];
}]];
}
Personデータで検索したプロパティでのみ比較しているので、検索項目を絞り込み結果を得ることが可能となる。上記のコードではARCを対応としてるため、「__bridge」でキャストをしてる。
また、iOS6からはアドレス帳へのアクセスにユーザへの同意を求める必要があるので、
ABAddressBookGetAuthorizationStatus()を使用してアクセス許可の状態を判断する処理が必要となる。
0 件のコメント:
コメントを投稿