0

I am retrieving vcard data from a vcf file from the app documents directory into a String. The string is fine but ABPersonCreatePeopleInSourceWithVCardRepresentation throws BAD_ACCESS error. Heres the code...

ABRecordRef defaultSource = ABAddressBookCopyDefaultSource(addressBook);
 NSData *data=[vcardString dataUsingEncoding:NSUTF8StringEncoding];
CFDataRef vCardData = (__bridge CFDataRef)data;
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
                if(granted)
                {
                    NSLog(@"%@",vcardString);
                    CFArrayRef vCardPeople = ABPersonCreatePeopleInSourceWithVCardRepresentation(defaultSource, vCardData);//BAD_ACCESS ERROR
                    for (CFIndex index = 0; index < CFArrayGetCount(vCardPeople); index++) {
                        ABRecordRef person = CFArrayGetValueAtIndex(vCardPeople, index);
                        ABAddressBookAddRecord(addressBook, person, NULL);
                        NSLog(@"added");
                    }

                    CFRelease(vCardPeople);
                    CFRelease(defaultSource);
                    ABAddressBookSave(addressBook, NULL);
                }
                else
                    NSLog(@"not granted");

Heres the NSLog vcardString...

BEGIN:VCARD

VERSION:3.0

PRODID:-//Apple Inc.//iOS 6.1//EN

N:;Home;;;

FN:Home

EMAIL;type=INTERNET;type=HOME;type=pref:carljosdsdsewhnson.akasdssh@gmail.com

TEL;type=CELL;type=VOICE;type=pref:2323454645

PHOTO;ENCODING=b;TYPE=JPEG:/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAICAgICAQICAgIC

....LOT OF GIBBERISH....

END:VCARD
Akash Malhotra
  • 1,106
  • 1
  • 17
  • 30

1 Answers1

1

You are using CFDataRef as required, but the memory management is out of whack. The completion handler will not be executed in line, and by that time data will have been deallocated. That makes vCardData a dangling pointer making a bad access. To fix this, instead of __bridge use __bridge_retained and then call CFRelease on vCardData once you are done.

ABRecordRef defaultSource = ABAddressBookCopyDefaultSource(addressBook);
 NSData *data=[vcardString dataUsingEncoding:NSUTF8StringEncoding];
CFDataRef vCardData = (__bridge_retained CFDataRef)data;
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
    if(granted)
    {
        NSLog(@"%@",vcardString);
        CFArrayRef vCardPeople = ABPersonCreatePeopleInSourceWithVCardRepresentation(defaultSource, vCardData);//BAD_ACCESS ERROR
        CFRelease(vCardData);
        for (CFIndex index = 0; index < CFArrayGetCount(vCardPeople); index++) {
        //...
borrrden
  • 33,256
  • 8
  • 74
  • 109