проблема с адресной книгой айфона

У меня возникла небольшая проблема с использованием адресной книги для получения имен контактов с устройства в моем собственном представлении контактов в моем приложении.

Код, который у меня есть, отлично работает на эмуляторе, но при тестировании на iPhone 4 он вылетает, приложение работает нормально, если есть два или меньше контактов, но 3 или более, и приложение вылетает.

Вот код, который я использую для получения имен контактов в массиве.

    ABAddressBookRef addressBook;
    bool wantToSaveChanges = YES;
    bool didSave;
    CFErrorRef error = NULL;

    addressBook = ABAddressBookCreate();

    listOfContacts = [[NSMutableArray alloc]init]; 

    int i;
    int len = (int) ABAddressBookGetPersonCount(addressBook);
    for(i = 1; i< (len+1); i++){

        ABRecordRef person = ABAddressBookGetPersonWithRecordID(addressBook, (ABRecordID) i);
        NSString* name = (NSString *)ABRecordCopyCompositeName(person);
        ABMultiValueRef number = (NSString *)ABRecordCopyValue(person,kABPersonPhoneProperty);
        NSString *mobileNum = (NSString *)ABMultiValueCopyValueAtIndex(number, 0 );

        NSLog(@"Name = %@", name);
        NSLog(@"Number = %@", mobileNum);

        [listOfContacts addObject:name]; 

        [name release];
        [mobileNum release];


    }


    if(ABAddressBookHasUnsavedChanges(addressBook)){
        if(wantToSaveChanges){
            didSave = ABAddressBookSave(addressBook, &error);
            if(!didSave){
                //Error
            }
        }
        else{
            ABAddressBookRevert(addressBook);
        }
    }

Когда он падает, это строка, которая выделяется в Xcode:

NSString* name = (NSString *)ABRecordCopyCompositeName(person);

И ошибка гласит:

Thread 1: Program received signal: "EXC_BAD_ACCESS"

Кто-нибудь может увидеть, в чем проблема? Я не понимаю, почему это будет работать на эмуляторе, но не на устройстве? А также почему работает до двух контактов, а не 3 и более??


person Donal Rafferty    schedule 26.04.2011    source источник
comment
Включите NSZombie, и мы сможем начать разговор. :)   -  person    schedule 26.04.2011
comment
Я сделал, но я использую XCode 4 (впервые использую xcode) и нашел, как его включить, но я не могу найти учебник о том, как использовать его в Xcode 4.   -  person Donal Rafferty    schedule 26.04.2011
comment
stackoverflow.com/ вопросы/2190227/   -  person Ruben Marin    schedule 26.04.2011


Ответы (3)


Просто предположение:

ABRecordRef person = ABAddressBookGetPersonWithRecordID(addressBook, (ABRecordID) i);

Эта линия кажется мне подозрительной. Я сомневаюсь, что идентификаторы записей пронумерованы от 1 до чего угодно. Особенно, если вы удалили запись.

Это объясняет, почему это работает на симуляторе, я думаю, вы просто добавили несколько тестовых контактов и никогда не удаляли их.

person Matthias Bauch    schedule 26.04.2011

Вот как я решил эту проблему:
(Обратите внимание, что я обязательно вызываю только активные записи, также я создал настраиваемый класс Contact)
Этот код заботится о крайних случаях, таких как: электронная почта/телефон не существует, или существует более одного раза...

+(NSArray *)getAddressBook{
    ABAddressBookRef addressBook;
    bool wantToSaveChanges = YES;
    bool didSave;
    CFErrorRef error = NULL;

    addressBook = ABAddressBookCreate();

    NSMutableArray *listOfContacts = [[NSMutableArray alloc]init]; 
    CFArrayRef array=ABAddressBookCopyArrayOfAllPeople(addressBook);

    int len=CFArrayGetCount(array);

    for (int i = 0; i<len; i++){
        ABRecordRef person = CFArrayGetValueAtIndex(array, i);
        if (ABRecordGetRecordType(person)==kABPersonType){

            NSString *firstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
            NSString *lastName = (NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);

            ABMultiValueRef emails = (ABMultiValueRef)ABRecordCopyValue(person,kABPersonEmailProperty);
            ABMultiValueRef numbers = (ABMultiValueRef)ABRecordCopyValue(person,kABPersonPhoneProperty);

            int sumEmails=ABMultiValueGetCount(emails);
            int sumNumbers=ABMultiValueGetCount(numbers);

            for (int j=0; j<(sumNumbers>sumEmails?sumNumbers:sumEmails); j++) {
                ACL_AB_Contact *contact=[[ACL_AB_Contact alloc]initWithFirstName:firstName LastName:lastName];

                if (j<sumEmails){
                    contact.emailAddress=(NSString *)ABMultiValueCopyValueAtIndex(emails,j);
                }

                if (j<sumNumbers){
                    contact.phoneNumber=(NSString *)ABMultiValueCopyValueAtIndex(numbers,j);
                }
                [contact logContact];
                [listOfContacts addObject:contact]; 
                [contact release];
            }

        }
    }

    if(ABAddressBookHasUnsavedChanges(addressBook)){
        if(wantToSaveChanges){
            didSave = ABAddressBookSave(addressBook, &error);
            if(!didSave){
                //Error
            }
        }
        else{
            ABAddressBookRevert(addressBook);
        }
    }
    return [listOfContacts autorelease];
}
person Applicasa iOS developer    schedule 08.05.2012

Идентификаторы записей являются динамическими. Это означает, что если вы добавите 2 контакта, а затем удалите первый, у вас останется только контакт с id "2". Поэтому я не буду использовать оператор for для доступа к контактам. Следуйте Руководство по программированию адресной книги

person Ruben Marin    schedule 26.04.2011