peoplePickerNavigationController leaks - iphone

I'm trying to get name and last name from Contacts and store the values in a couple of NSString:
CFStringRef cfName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
self.stName = (NSString *)cfName;
CFRelease(cfName);
CFStringRef cfLastname = ABRecordCopyValue(person, kABPersonLastNameProperty);
self.stLastname = (NSString *)cfLastname;
CFRelease(cfLastname);
The problem is, if firstname or lastname are empty in contacts, when I release the CFStringRef the app crash with EXC_BAD_ACCESS (zombie?).
If I don't release the CFStringRef I have a leak.
Any suggestion is appreciated.
Max

Yes, CFRelease will crash (halt) if you pass it a NULL argument.
This was allready mentioned by sbooth here.
CFRelease looks like this:
void CFRelease(CFTypeRef cf) {
if (NULL == cf) HALT; //this line will get you
#if DEPLOYMENT_TARGET_MACOSX || DEPLOYMENT_TARGET_EMBEDDED
if (CF_IS_COLLECTABLE(cf)) {
if (CFTYPE_IS_OBJC(cf)) {
// release the GC-visible reference.
auto_zone_release(auto_zone(), (void*)cf);
} else {
// special-case CF objects for better performance.
_CFRelease(cf);
}
return;
}
#endif
source
Therefor it's your responcibility to check if you're passing it a NULL or not.
You were correct in your (deleted) answer. Code should look like:
CFStringRef cfName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
self.stName = (NSString *)cfName;
if (self.stName) CFRelease(cfName);
CFStringRef cfLastname = ABRecordCopyValue(person, kABPersonLastNameProperty);
self.stLastname = (NSString *)cfLastname;
if (self.stLastname) CFRelease(cfLastname);
You still might get compiler warnings but this code should work fine.

Related

App crashes when fetching record from address book

I need to fetch record from address book. I'm using ABPeoplePickerNavigationController to do so. While fetching record I'm putting a check condition to check record exist or not.
For example to check there is first name I'm using the following code
NSString *fname;
CFTypeRef fnameProperty = ABRecordCopyValue(person, kABPersonFirstNameProperty);
if (ABRecordCopyValue(person, kABPersonFirstNameProperty)) {
fname = (__bridge NSString*)fnameProperty;
}
else{
fname = #"";
}
The code works perfectly for kABPersonFirstNameProperty.
But when I'm using following piece of code to check email property
ABMultiValueRef emailProperty = ABRecordCopyValue(person, kABPersonEmailProperty);
NSLog(#"%#",emailProperty);
NSString *email;
if (ABRecordCopyValue(person, kABPersonEmailProperty)) {
email = (__bridge NSString*)ABMultiValueCopyValueAtIndex(emailProperty, 0);
}
else {
email = #"";
}
My app crashes if kABPersonEmailProperty is nil(there is no email property stored for the person)
Can somebody explain me why is this happening?
Thanks
Here's is my working version, see if this works.
//Email
NSString* email = nil;
ABMultiValueRef emailNum = ABRecordCopyValue(person,
kABPersonEmailProperty);
if (ABMultiValueGetCount(emailNum) > 0) {
email = (__bridge_transfer NSString*)
ABMultiValueCopyValueAtIndex(emailNum, 0);
} else {
email = #"";
}

Call to function 'CFUUIDCreate' returns a Core Foundation object with a +1 retain count

Added share kit group to the project and found so many compile warnings fixed most of them but few are still showing.
This one is from OAMutableURLRequest.m class
- (void)_generateNonce
{
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
NSMakeCollectable(theUUID);// **Reference count decremented on this line**
nonce = (NSString *)string; //**Incorrect decrement of the reference count of an object that is not owned at this point by the caller on this line**
}
Have no idea how to fix this one.
Thanks for help.
Solved it. Actually i was not share that what to release in this case but when i added
- (void)_generateNonce
{
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
NSMakeCollectable(theUUID);
nonce = (NSString *)string;
//[string autorelease];
CFRelease (theUUID);
}
It worked. Looks like i was responsible to release the theUUID which i allocated in CFUUIDCreate.

release CFString

I use this code to get the last name of ABPerson
CFStringRef lastNameRef = ABRecordCopyValue((ABRecordRef)personRecordRef, kABPersonLastNameProperty);
NSString *friendLastName = (NSString*)lastNameRef;
CFRelease(lastNameRef);
it work fine when the value of last name is not equal to NULL
but when the this value is NULL the application crash at the third line because I try to relese NULL
the question is witch is the best way to releasing the CFString in this case without causing the crash of the application
Just use an if to check for NULL.
if (lastNameRef != NULL)
CFRelease(lastNameRef);
CFRelease is old C style code. One should check for NULL before calling CFRelease as also set lastNameRef to NULL after calling CFRelease.
if (lastNameRef != NULL)
{
CFRelease(lastNameRef);
lastNameRef = NULL;
}
CFRelease expects a non-NULL pointer. You could check for that with an if statement, but it is easier to simply release or autorelease friendLastName instead:
CFStringRef lastNameRef = ABRecordCopyValue((ABRecordRef)personRecordRef, kABPersonLastNameProperty);
NSString *friendLastName = (NSString*)lastNameRef;
// use friendLastName
[friendLastName release];
or
CFStringRef lastNameRef = ABRecordCopyValue((ABRecordRef)personRecordRef, kABPersonLastNameProperty);
NSString *friendLastName = (NSString*)lastNameRef;
[friendLastName autorelease];
// use friendLastName
As you don't seem to use lastNameRef, you could also inline that variable:
NSString *friendLastName = (NSString*)ABRecordCopyValue((ABRecordRef)personRecordRef, kABPersonLastNameProperty);
// use friendLastName
[friendLastName release];
or
NSString *friendLastName = (NSString*)ABRecordCopyValue((ABRecordRef)personRecordRef, kABPersonLastNameProperty);
[friendLastName autorelease];
// use friendLastName

app crashes when using kABPersinPhoneProperty

I am trying to get all the phone number from the Phone Book of iPhone. But my app crashes as soon as I try to fetch the number using kABPersonPhoneProperty. The code snippet is here
ABAddressBookRef addressBook = ABAddressBookCreate();
NSMutableArray *allPeople = (NSMutableArray*)ABAddressBookCopyArrayOfAllPeople(addressBook);
int nPeople = ABAddressBookGetPersonCount(addressBook);
CFRelease(addressBook);
for(int i=0; i < nPeople; i++ ){
ABRecordRef person = [allPeople objectAtIndex:i];
NSString *name = #"";
CFTypeRef fName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
CFTypeRef lName = ABRecordCopyValue(person, kABPersonLastNameProperty);
ABMultiValueRef multi = ABRecordCopyValue(person , kABPersonPhoneProperty);
NSString *number = (NSString *)ABMultiValueCopyValueAtIndex(multi, 0);
if ([number length] > 0) {
if(fName != NULL)
{
if (lName != NULL) {
name = [[NSString stringWithFormat:#"%#", fName] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}
else {
name = [[NSString stringWithFormat:#"%#", fName] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}
NSLog(#"Number==>%# ",number);
}
}
if (fName != NULL) {
CFRelease(fName);
}
if (lName != NULL) {
CFRelease(lName);
}
if (multi != NULL) {
CFRelease(multi);
}
}
[allPeople release];
I am unable to figure out the error in this. I am also releasing everything even then it is not running smoothly.
I am even getting potential memory leak when running build and analyze for the code part
ABMultiValueRef multi = ABRecordCopyValue(person , kABPersonPhoneProperty);
NSLog(#"Number===>%d" , ABMultiValueGetCount(multi));
Please help me out to come.
Any kind of help would be highly appreciated.
Thanks in advance
Thanks for the response. I have figured out the solution fot the problem here. I did not release number variable thinking that the reference was passed as reference but it is copied to the returned location, hence need to release number after the usage.
thanks again for all the responses!!

kABPersonAddressProperty causes crashes under ABAddressBookGetPersonWithRecordID

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