potential leak of an object stored into address book - iphone

I got issue potential leak of an object stored into address book, how to resolve it.
I create address book locally and then copyArrayofAllpeople to people1 array. people1 array used outside of method. So where should I release addressbookref. Please make suggestions.
This is my code
ABAddressBookRef addressBook = ABAddressBookCreate();
people1 = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);

Use CFRelease() method.
ABAddressBookRef addressBook = ABAddressBookCreate();
people1 = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
CFRelease(addressBook);
I think it will be helpful to you.

Related

Not creating address book object

I have implemented the code to get contact list form address book. For that I have used this code
ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allSources = ABAddressBookCopyArrayOfAllPeople( addressBook );
CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );
and when this code is executing then my app is crashing and in crash report I got that
Exception Type: EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x000000000000defe
Crashed Thread: 5
And I am testing on iPhone 3GS with ios 6.0.
So how I fix this bug?
Thanks for support and I got the solution. Solution of my issue is
ABAddressBookRef addressBook = ABAddressBookCreate();
This is deprecated in ios 6.0.
Use this code ,it will give you the objects list.
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
NSArray *persons = (NSArray *)(ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByFirstName));

contact notes are not transferred when exporting/importing via the built-in vCard representation methods

Using the ABPersonCreateVCardRepresentationWithPeople method for export, and the ABPersonCreatePeopleInSourceWithVCardRepresentation for import, I have successfully transfered contact data between devices. However, the data in the contact's "notes" field isn't transfered.
Here's my export function:
+(NSData*)exportContactsToVcard:(NSArray*)contacts
{
NSMutableArray *people = [NSMutableArray arrayWithCapacity:contacts.count];
ABAddressBookRef ab = ABAddressBookCreate();
for (Contact *contact in contacts)
{
ABRecordRef person = ABAddressBookGetPersonWithRecordID(ab,contact.contactId);
[people addObject:(__bridge id)person];
}
NSData *vCard = (__bridge NSData*)ABPersonCreateVCardRepresentationWithPeople((__bridge CFArrayRef) people);
return vCard;
}
and part of my import function:
+(NSArray*)importContactsFromVcardData:(NSData*)vcardData
{
NSMutableArray *addedContactIds = [NSMutableArray array];
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef defaultSource = ABAddressBookCopyDefaultSource(addressBook);
NSArray *createdPeople = (__bridge_transfer NSArray*)ABPersonCreatePeopleInSourceWithVCardRepresentation(defaultSource,(__bridge CFDataRef)vcardData);
CFErrorRef error = NULL;
for (id person in createdPeople)
{
error = NULL;
ABRecordRef personRecord = (__bridge ABRecordRef)person;
NSString *notes = (__bridge NSString *)ABRecordCopyValue(personRecord, kABPersonNoteProperty);
In the last line, notes is always nil, even if the contact had notes before it was exported. All the other standard contact fields seem to be in place.
For example, if I replace the last line with:
NSString *firstName = (__bridge NSString *)ABRecordCopyValue(personRecord, kABPersonFirstNameProperty);
the firstName string will hold the contact's first name.
Any idea how I can work around this, and get the contact notes?
Thanks.
For testing purposes, you can export a vCard from Address Book. Then drag it to TextEdit to look at the various fields.
At the bottom you'll find something like this:
NOTE:This is a note!
Also, see this link for info on the vCard format:
http://en.wikipedia.org/wiki/VCard
ABPersonCreateVCardRepresentationWithPeople will only transfer the important contact details of a vCard...thats my identifying in much tests with the vCard and the iOS import-export function. It has many mistakes, e.g. if you try to import it with social networks like facebook, it won't do it with (just look in my other thread THREADLINK )
But if you try to add some vCard Information over ABNewPersonViewController, it will work perfectly.

Setting person properties

Working on someone else's code. I am really confused about whats exactly happening in this code.
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef persons = ABAddressBookGetPersonWithRecordID(addressBook, x);
CFErrorRef *error=NULL;
ABAddressBookRemoveRecord(addressBook, persons, error);
ABAddressBookSave(addressBook, error);
ABRecordRef persons = ABPersonCreate();
ABRecordSetValue(persons, kABPersonFirstNameProperty, firstName , nil);
What should be done is that, a ABRecordRef person should be created. His properties should be set and his record/details should be displayed. He should never be saved in the address book. Is this the way to do it. Need help.
Edit: Apart from setting properties to person, the following code is added to push the view controller to view the person.
MyContactDetailViewcontroller *personContactDetail = [[MyContactDetailViewcontroller alloc] init];
personContactDetail.displayedPerson = persons;
personContactDetail.passedSelectedContactData = selectedContactsOnlyData;
[self.navigationController pushViewController:personContactDetail animated:YES];
[personContactDetail release];
MyContactDetailViewcontroller subclass ABPersonViewController. Or is it more apt to use ABUnknownPersonViewController.
Do you find any cases where the contacts could be duplicated in address book
This is exactly what is happening here.. I will explain..
ABAddressBookCreate creates a new address book from data from the addressbook database, so any changes you make to ABAddressBookRef will only be saved to actual addressbook database once you call ABAddressBookSave(). so what it is doing is getting the reference for the person with recordid- x. Than you are creating a new person entry using
ABRecordRef persons = ABPersonCreate();
and than you are setting its value, but this is available to this particular object and not stored in the database unless you call... ABAddressBookSave()
hoping this helps you... :)

Memory leak with CFArray in ARC

I've made an iPhone app using ARC that accesses every entry in the address book, and then every address for every person. The data is stored in CFArrays, which are toll-free bridged to NSArrays. The code is below.
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef arrayRef = ABAddressBookCopyArrayOfAllPeople(addressBook);
NSArray *peopleArray =[(__bridge NSArray *) arrayRef copy];
CFRelease(arrayRef);
arrayRef = nil;
for(id personId in peopleArray)
{
ABRecordRef person = (__bridge ABRecordRef) personId;
//process other attributes of the address book
ABMultiValueRef multi = ABRecordCopyValue(person, kABPersonAddressProperty);
CFArrayRef addressRef = ABMultiValueCopyArrayOfAllValues(multi);
NSArray *addressArray = [(__bridge NSArray *) addressRef copy];
for(NSDictionary *address in addressArray)
{
//process the addresses
}
CFRelease(addressRef);
addressRef = nil;
}
From what I've researched on the internet and in Apple's Memory Management guides, this looks like the proper way to do it. The problem is when I got to run the code, it halts on "CFRelease(addressRef)", highlighted green with text "Thread 1" (not sure what this error means). I've also tried putting the CFRelease before the for loop, but the same issue occurs.
If I remove the CFRelease, it compiles, but there is a memory leak at the creation of addressArray. Does anyone know how to solve this problem? I can't seem to figure it out using ARC.
Instead of NSArray *peopleArray =[(__bridge NSArray *) arrayRef copy]; CFRelease(arrayRef);, use NSArray *peopleArray = CFBridgingRelease(arrayRef). This transfers ownership of the object to ARC.
Whenever you see "Copy" in a method name you should use (__bridge_transfer <ObjectType> *)
Then ARC will be responsible for releasing the object.
So your code will look like:
NSArray *peopleArray = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);

EXC_BAD_ACCESS when add vCard data to AddressBook

I follow this instruction to add vcard data to addressbook, in my project. iOS 5.
Adding vCard data directly to the system Address Book
The code run ok, and add vcard data to adressbook in my ipad2 and iphone4s, however, xcode show this error:
thread 1 program received signal: "exc_bad_acess"
Why this error appears?
EDIT: code add.
NSString *vCardString =
#"BEGIN:VCARD\n"
#"N:Paulo;Joao\n"
#"TEL:+44 (0)9999 8888\n"
#"ADR;HOME:;;Flat 2, 43 Howitt Road, Belsize Park;London;;NW34LU;UK\n"
#"ORG:NetTek Ltd;\n"
#"TITLE:Consultant\n"
#"EMAIL:none#none.com\n"
#"URL:www.none.com\n"
#"BDAY:19001010\n"
#"END:VCARD";
CFDataRef vCardData = (__bridge CFDataRef)[vCardString dataUsingEncoding:NSUTF8StringEncoding];
ABAddressBookRef book = ABAddressBookCreate();
ABRecordRef defaultSource = ABAddressBookCopyDefaultSource(book);
CFArrayRef vCardPeople = ABPersonCreatePeopleInSourceWithVCardRepresentation(defaultSource, vCardData);
for (CFIndex index = 0; index < CFArrayGetCount(vCardPeople); index++)
{
ABRecordRef person = CFArrayGetValueAtIndex(vCardPeople, index);
ABAddressBookAddRecord(book, person, NULL);
CFRelease(person);
}
CFRelease(vCardPeople);
CFRelease(defaultSource);
ABAddressBookSave(book, NULL);
CFRelease(book);
I found the problem.
The problem is with the last line, probably because of ARC.
CFRelease(book);
I commented the line, and the program run normally.
I'm glad you were able to find the problem, however, I just thought I'd let you know that it's not an ARC thing but a memory leak thing. You're over-releasing data the the OS wants to release itself. Here's an explanation.
Additionally, please mark the question as answered so you can help other people find the solution. Thank you!