由于奇怪的内存问题,从联系人中读取电子邮件地址失败

发布于 2024-08-28 00:40:55 字数 1657 浏览 5 评论 0原文

我很困惑。

我正在尝试获取一个人拥有的所有电子邮件地址的列表。 我正在使用 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 keep]: message sent to deallocated instance 0x4e9dc60

错误。

但是等等,还有更多!我可以通过两种方法之一来修复它。

首先,我可以取消函数顶部 NSLog 的注释。我每次都会从 NSLog 的 ABRecordCopyValue 中得到泄漏,但代码似乎运行良好。

另外,我可以在最后注释掉

CFRelease(multi);

,它的作用完全相同。静态编译错误,但运行代码。

所以如果没有泄漏,这个函数就会崩溃。为了防止崩溃,我需要让内存失血。两者都不是一个很好的解决方案。

谁能指出发生了什么事吗?

I'm stumped.

I'm trying to get a list of all the email address a person has.
I'm using the ABPeoplePickerNavigationController to select the person, which all seems fine. I'm setting my

ABRecordRef personDealingWith;

from the person argument to

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

and everything seems fine up till this point.
The first time the following code executes, all is well.
When subsequently run, I can get issues. First, the code:

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

If compiled as written, the are no errors or static analysis problems. This crashes with a

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

error.

But wait, there's more! I can fix it in either of two ways.

Firstly, I can uncomment the NSLog at the top of the function. I get a leak from the NSLog's ABRecordCopyValue every time through, but the code seems to run fine.

Also, I can comment out the

CFRelease(multi);

at the end, which does exactly the same thing. Static compilation errors, but running code.

So without a leak, this function crashes. To prevent a crash, I need to haemorrhage memory. Neither is a great solution.

Can anyone point out what's going on?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦里兽 2024-09-04 00:40:55

事实证明,我没有正确存储 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;
}

It turned out that I wasn't storing the ABRecordRef personDealingWith var correctly. I'm still not sure how to do that properly, but instead of having the functionality in another routine (performed later), I'm now doing the grunt-work in the delegate method, and using the derived results at my leisure. The new (working) routine:

- (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;
}
黯淡〆 2024-09-04 00:40:55

我遇到了类似的问题。问题可能在于你如何设置你的

ABRecordRef personDealingWith;

似乎你不能这样做:

ABRecordRef personDealingWith = person;

因为 personDealingWith 仍然为空。相反,我所做的是:

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

I ran into a similar problem. The problem might lie at how you set your

ABRecordRef personDealingWith;

It seems that you can't just do:

ABRecordRef personDealingWith = person;

Because personDealingWith remains null. Instead what I did is:

ABRecordID personID = ABRecordGetRecordID(person);
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
personDealingWith = ABAddressBookGetPersonWithRecordID(addressBook, personID);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文