Не удается прочитать адрес электронной почты из контактов из-за странной проблемы с памятью

Я в тупике.

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

ABRecordRef personDealingWith;

из аргумента person в

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {

и до этого момента все кажется прекрасным. При первом выполнении следующего кода все в порядке. При последующем запуске могут возникнуть проблемы. Во-первых, код:

// following line seems to make the difference (issue 1)
// NSLog(@"%d", ABMultiValueGetCount(ABRecordCopyValue(personDealingWith, kABPersonEmailProperty)));

// construct array of emails
ABMultiValueRef multi = ABRecordCopyValue(personDealingWith, kABPersonEmailProperty);
CFIndex emailCount = ABMultiValueGetCount(multi);

if (emailCount > 0) {
    // collect all emails in array
    for (CFIndex i = 0; i < emailCount; i++) {
        CFStringRef emailRef = ABMultiValueCopyValueAtIndex(multi, i);
        [emailArray addObject:(NSString *)emailRef];
        CFRelease(emailRef);
    }
}

// following line also matters (issue 2)
CFRelease(multi);

Если скомпилирован так, как написано, ошибок или проблем статического анализа не будет. Это вылетает с

*** -[Not A Type retain]: message sent to deallocated instance 0x4e9dc60

ошибка.

Но подождите, это еще не все! Я могу исправить это любым из двух способов.

Во-первых, я могу раскомментировать NSLog в верхней части функции. Я получаю утечку из ABRecordCopyValue NSLog каждый раз, но код работает нормально.

Также я могу прокомментировать

CFRelease(multi);

в конце, что делает то же самое. Статические ошибки компиляции, но код запущен.

Так что без утечки эта функция вылетает. Чтобы предотвратить сбой, мне нужно кровоточить память. И тоже не лучшее решение.

Кто-нибудь может указать на то, что происходит?


person DefenestrationDay    schedule 10.04.2010    source источник


Ответы (2)


Оказалось, что я неправильно хранил ABRecordRef personDealingWith var. Я все еще не уверен, как это сделать правильно, но вместо того, чтобы иметь функциональность в другой подпрограмме (выполненной позже), я теперь выполняю чертову работу в методе делегата и использую полученные результаты на досуге. Новый (рабочий) распорядок:

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {
    // as soon as they select someone, return
    personDealingWithFullName = (NSString *)ABRecordCopyCompositeName(person);
    personDealingWithFirstName = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
    // construct array of emails
    [personDealingWithEmails removeAllObjects];
    ABMutableMultiValueRef multi = ABRecordCopyValue(person, kABPersonEmailProperty);
    if (ABMultiValueGetCount(multi) > 0) {
        // collect all emails in array
        for (CFIndex i = 0; i < ABMultiValueGetCount(multi); i++) {
            CFStringRef emailRef = ABMultiValueCopyValueAtIndex(multi, i);
            [personDealingWithEmails addObject:(NSString *)emailRef];
            CFRelease(emailRef);
        }
    }
    CFRelease(multi);
    return NO;
}
person DefenestrationDay    schedule 27.06.2011

Я столкнулся с похожей проблемой. Проблема может заключаться в том, как вы установите

ABRecordRef personDealingWith;

Кажется, нельзя просто так:

ABRecordRef personDealingWith = person;

Поскольку personDealingWith остается нулевым. Вместо этого я сделал следующее:

ABRecordID personID = ABRecordGetRecordID(person);
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
personDealingWith = ABAddressBookGetPersonWithRecordID(addressBook, personID);
person user2847666    schedule 16.06.2014