Поиск ABAddressbook iOS SDK

Я хочу найти в адресной книге iPhone определенный номер телефона, а затем получить имя контакта. В настоящее время я перебираю все контакты, извлекаю многозначные свойства и сравниваю их со значением. Это отнимает слишком много времени. Я прочитал руководство по адресной книге Apple, и они говорят:

«выполнить другие виды поиска, использовать функцию ABAddressBookCopyArrayOfAllPeople, а затем отфильтровать результаты с помощью метода NSArray filteredArrayUsingPredicate:».

Может ли кто-нибудь дать мне пример того, как именно это сделать?

Спасибо.


person Rabih    schedule 01.03.2011    source источник
comment
это было бы помощью. это мой ответ на другой вопрос, stackoverflow.com/questions/4272164/   -  person ChangUZ    schedule 05.08.2011
comment
Вот наиболее эффективный способ сделать это с помощью NSPredicate: hesh.am/2012/10/   -  person Hesham    schedule 21.11.2012


Ответы (4)


Если вы хотите сделать поиск в контактах по номеру телефона, то скажу одно предложение.

1.Получить все контакты

NSArray *thePeoples = (NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook);

2. Создайте еще один массив (записи) из массива контактов (люди),

записи: [запись1, запись2, ....записьN]

запись: {имя: "myContactName", номер телефона: "1234567890"}

3. Найдите изменяемый массив (записи) с помощью предиката.

NSPredicate * myPredicate = [NSPredicate predicateWithFormat:@"record.phoneNumber contains %@",string];

NSArray * filteredArray = [records filteredArrayUsingPredicate:myPredicate];

Это всего лишь простой пример вашего решения, и помните, что phoneNumber — это поле с несколькими значениями. Поэтому мы включим массив в качестве номера телефона в переменную класса модели.

person Jay    schedule 08.06.2011
comment
Что вы подразумеваете под созданием другого массива из массива контактов? - person AlBeebe; 06.11.2011
comment
Как это работает? [‹__NSCFType 0x6e1f220› valueForUndefinedKey:]: этот класс не соответствует кодированию значения ключа для записи ключа. - person John Lane; 29.11.2012

Следующий метод вернет массив, содержащий все контакты с заданным номером телефона. Этот метод занял 0,02 секунды для поиска 250 контактов на моем iPhone 5 под управлением iOS7.

#import <AddressBook/AddressBook.h>


-(NSArray *)contactsContainingPhoneNumber:(NSString *)phoneNumber {
    /*

     Returns an array of contacts that contain the phone number

     */

    // Remove non numeric characters from the phone number
    phoneNumber = [[phoneNumber componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]] componentsJoinedByString:@""];

    // Create a new address book object with data from the Address Book database
    CFErrorRef error = nil;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
    if (!addressBook) {
        return [NSArray array];
    } else if (error) {
        CFRelease(addressBook);
        return [NSArray array];
    }

    // Requests access to address book data from the user
    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {});

    // Build a predicate that searches for contacts that contain the phone number
    NSPredicate *predicate = [NSPredicate predicateWithBlock: ^(id record, NSDictionary *bindings) {
        ABMultiValueRef phoneNumbers = ABRecordCopyValue( (__bridge ABRecordRef)record, kABPersonPhoneProperty);
        BOOL result = NO;
        for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
            NSString *contactPhoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
            contactPhoneNumber = [[contactPhoneNumber componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]] componentsJoinedByString:@""];
            if ([contactPhoneNumber rangeOfString:phoneNumber].location != NSNotFound) {
                result = YES;
                break;
            }
        }
        CFRelease(phoneNumbers);
        return result;
    }];

    // Search the users contacts for contacts that contain the phone number
    NSArray *allPeople = (NSArray *)CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
    NSArray *filteredContacts = [allPeople filteredArrayUsingPredicate:predicate];
    CFRelease(addressBook);

    return filteredContacts;
}
person AlBeebe    schedule 16.01.2014

Использовать это. это мой код. Сделать массив для поиска.

        NSLog(@"=====Make People Array with Numbers. Start.");
        peopleWithNumber = [[NSMutableDictionary alloc] init];
        for (int i=0; i < [people count]; i++) {
            NSInteger phoneCount = [self phoneCountAtIndex:i];
            if (phoneCount != 0) {
                NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
                for (int j=0 ; j < phoneCount ; j++) {
                    [phoneNumbers addObject:[self phoneNumberAtIndex:i phoneIndex:j]];
                }
                [peopleWithNumber addEntriesFromDictionary:
                 [NSDictionary dictionaryWithObjectsAndKeys:
                  [NSArray arrayWithArray:phoneNumbers],    [self fullNameAtIndex:i], nil]];
            }
        }
        NSLog(@"=====Make People Array with Numbers. End.\n");

Поисковый метод. это (люди с числом) будет быстрее, чем использование массива (люди)

"NSArray *people = (NSArray *) ABAddressBookCopyArrayOfAllPeople (адресная книга);"

- (NSArray *)searchNamesByNumber:(NSString *)number {

    NSString *predicateString = [NSString stringWithFormat:@"%@[SELF] contains '%@'",@"%@",number];
    NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:predicateString,peopleWithNumber,number];
    NSArray *names = [[peopleWithNumber allKeys] filteredArrayUsingPredicate:searchPredicate];

    return names;
}
person ChangUZ    schedule 08.08.2011

Вы не можете использовать predicateWithFormat с массивом непрозрачных типов ABRecordRef. Но вы можете использовать predicateWithBlock:

[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
    ABRecordRef person=(__bridge ABRecordRef)evaluatedObject;
    CFTypeRef theProperty = ABRecordCopyValue(person, kABPersonPhoneProperty);
    NSArray *phones = (__bridge_transfer NSArray *) ABMultiValueCopyArrayOfAllValues(theProperty);
    CFRelease(theProperty);
    BOOL result=NO;
    for (NSString *value in phones) {
        if ([value rangeOfString:@"3"].location!=NSNotFound) {
            result=YES;
            break;
        }
    }
    return result;
}];
person javieralog    schedule 05.07.2012