views:

67

answers:

2

I am trying to be an ABRecordRef that represents the contact info of a person from addressbook. I built two functions that calls a function to fill in a personal data structure with the info in ABRecordRef.

Here comes the function declarations for the three functions:

+ (NSMutableArray*) getAllContactProfiles{

    NSMutableArray *listOfProfile = [[NSMutableArray alloc] init];

    //---get the contact information for the api
    ABAddressBookRef addressBook = ABAddressBookCreate(); 
    CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
    CFIndex numberOfPeopleInAddressBook = ABAddressBookGetPersonCount(addressBook);

    //<- Here I loop through all the contacts and pass the ABRecordRef into the following function

    //---release the variables---
    CFRelease(addressBook);
    CFRelease(people);
    [listOfProfile autorelease];

    return listOfProfile;
}

The Following Function

+ (MSProfileEntry*) getPersonProfileThroughABRecordRef:(ABRecordRef) person{

    MSProfileEntry *mockProfile;
    ABRecordID recID=ABRecordGetRecordID(person);
    //get the user name
    CFStringRef firstName;
    firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);//it goes wrong here!
    CFStringRef lastName;
    lastName = ABRecordCopyValue(person, kABPersonLastNameProperty);
    //bla bla bla.. the rest of the code
}

Everything goes very well. However, when I try to get the ABRecordRef through ABAddressBookGetPersonWithRecordID like it is in the next method:

The Next Method

+ (MSProfileEntry*) getPersonProfileThroughContactId:(NSInteger*)contactId{
    ABAddressBookRef addressBook = ABAddressBookCreate();
    ABRecordRef person = 
    ABAddressBookGetPersonWithRecordID(addressBook, (ABRecordID)contactId);
    CFRelease(addressBook);
    if (person == nil) {
        return nil;
    }
    return [MSContactUtil getPersonProfileThroughABRecordRef:person];
}

The whole app crashes on line:ABRecordCopyValue(person, kABPersonFirstNameProperty);.

The problem now is that ABRecordCopyValue(person, kABPersonFirstNameProperty); works perfectly fine with ABAddressBookCopyArrayOfAllPeople but causes the app to crash with ABAddressBookGetPersonWithRecordID.

Does anyone have any clue how to solve this problem? I really don't want to loop through entire contact base just to look for a contact.

+1  A: 

Two things:

  • You pass (NSInteger*)contactId to getPersonProfileThroughContactId and after that you call ABAddressBookGetPersonWithRecordID(addressBook, (ABRecordID)contactId);. Actually you pass an address of the integer that holds the contact id and not the id itself...
  • You check if (person == nil), BUT person may not be nil - you should compare with NULL. I believe that it IS NULL in your case (because of my previous point).

These 2 things together cause the crash.

Just pass an integer as is - not its address...

EDIT:
Like this:

+ (MSProfileEntry*)getPersonProfileThroughContactId:(NSInteger)contactId
Michael Kessler
Thanks! I will give it a try!
Winston Chen
I have edited my answer. See the `getPersonProfileThroughContactId` method as it should be...
Michael Kessler
A: 

It turned out to be a memory issue. I forgot to retain the "addressBook". By the time I executed the following line:

firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);

The "addressBook" had been cleaned out already. Somehow we still need "addressBook" while querying for the detail information in "person".

So, remember to put in the following line, and you will be safe.

CFRetain(addressBook);

Winston Chen