Търсете 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. Създайте друг масив (записи) от масива с контакти (thePeoples),

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

запис: {име:"myContactName", phoneNumber:"1234567890"}

3. Търсене в mutableArray(records) с предикат.

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");

Метод на търсене. it(peopleWithNumber) би било по-бързо от използването на array(people)

"NSArray * хора = (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