I want fetch all phone numbers from address book and i want to store in one array.
For that am writing this code,but am getting this error at second line Program received signal: “EXC_BAD_ACCESS”
ABRecordRef person;
ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSArray* phoneNumbers = (NSArray*)ABMultiValueCopyArrayOfAllValues(phoneNumberProperty);
// CFRelease(phoneNUmberProperty);
NSLog(#"Phone numbers = %#", phoneNumbers);
[phoneNumbers release];
please help me what are changes can i do.
Thanks in advance
ABRecordCopyValue will not get you all the phone numbers of a address book. You can use this to look up a property of 1 person. Use ABAddressBookCopyArrayOfAllPeople to get all the persons from the address book first.
Related
For a Unified Info contact (iOS6 - the Facebook and Cloud and whatever dog and cat unification) has made the code below to constantly return [None]. Any help to get this working again would be appreciated. Thank u!
NSString* phone = nil;
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
if (ABMultiValueGetCount(phoneNumbers) > 0) {
phone = (NSString*)ABMultiValueCopyValueAtIndex(phoneNumbers, 0);
} else {
phone = #"[None]";
}
Found the solution here works well:
iOS 6 address book empty kABPersonPhoneProperty
"To retrieve all phone numbers you need to get all linked contacts and then look for phone numbers in that contacts."
using iOS sdk 4.3
In order to determine the phone numbers a contact has on iOS one can use the code below
ABMutableMultiValueRef multi = ABRecordCopyValue(person, kABPersonPhoneProperty);
CFIndex i = ABMultiValueGetIndexForIdentifier (multi,identifier);
phoneNumberLabel = (CFStringRef)ABMultiValueCopyLabelAtIndex(multi, i);
phoneNumber = (NSMutableString* )ABMultiValueCopyValueAtIndex(multi, i);
However what property type ie kABPersonxxxProperty will give me the string value of the Ringtone for a contact. This is all i need, just to read the string.
Thanks
When I try to retrieve phone numbers from Address Book contacts, the result is always nil if the contact has an e-mail address. This is obviously a big problem...such a big one, in fact, that I have a hard time believing I'm not doing something wrong. But every test I've done--including using other, unrelated code samples--gives the same result.
I've used the code below to successfully retrieve email addresses:
+ (NSArray*)emailFromRecordRef:(ABRecordRef)personRef
{
ABMultiValueRef emailAddressesRef = ABRecordCopyValue(personRef, kABPersonEmailProperty);
NSArray* emailAddresses = nil;
if (emailAddressesRef != nil)
{
emailAddresses = [(NSArray*)ABMultiValueCopyArrayOfAllValues(emailAddressesRef) autorelease];
CFRelease(emailAddressesRef);
}
return emailAddresses;
}
...but when I adapt the same code to retrieve phone numbers:
+ (NSArray*)phoneNumbersFromRecordRef:(ABRecordRef)personRef
{
ABMultiValueRef phoneNumbersRef = ABRecordCopyValue(personRef, kABPersonPhoneProperty);
NSArray* phoneNumbers = nil;
if (phoneNumbersRef != nil)
{
phoneNumbers = [(NSArray*)ABMultiValueCopyArrayOfAllValues(phoneNumbersRef) autorelease];
CFRelease(phoneNumbersRef);
}
return phoneNumbers;
}
...it only retrieves phone numbers for users that don't have email addresses. If they have email addresses, no phone numbers are returned.
Has anyone out there successfully retrieved phone numbers from Address Book contacts?
Thanks.
Turns out, of course, I was doing something wrong. Apparently you need to keep the reference to AddressBook alive (retained) during the entire time you're requesting additional attributes like phone numbers. When I kept it alive, the phone number issue went away.
Is there any way to edit a contact programmatically in the iPhone? For example, I want to modify a contact which is returned by ABPeoplePickerNavigationController. How can I do this? I have:
(BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
NSString *phoneNum = #"01234567890";
ABAddressBookRef addressBook = ABAddressBookCreate();
contact = ABAddressBookGetPersonWithRecordID(addressBook, ABRecordGetRecordID(person));
if(phoneNum && contact != NULL)
{
ABMutableMultiValueRef phoneNumberMultiValue = ABMultiValueCreateMutable(kABMultiStringPropertyType);
ABMultiValueAddValueAndLabel(phoneNumberMultiValue, phoneNum, kABPersonPhoneMobileLabel, NULL);
[self dismissModalViewControllerAnimated:YES];
ABRecordSetValue(contact, kABPersonPhoneProperty, phoneNumberMultiValue, nil);
//THIS CODE IS NOT BEHAVING AS I EXPECTED,
//if(ABAddressBookHasUnsavedChanges(addressBook))//Anyway this needs to be checked
{
ABAddressBookSave(addressBook, NULL);
}
}
return NO;
}
The call to ABAddressBookSave(addressBook, NULL); is working. But the problem is, all the old information of the "contact" is removed from the address book and only the "phoneNum" is saved at the end.
How can I solve this problem?
Apologies for the previous answer - I read the question wrong...! I thought that the contact wasn't saving at all on the address book.
It seems that the only information lost is the contact's other phone numbers, correct? Meaning that the ABRecordRef's other details, such as address, notes, birthdates, etc. remain intact.
If this is correct, I assume that the only feasible way to counter this deletion of other phone numbers is to simply append a PhoneLabel to the contact's existing kABPersonPhoneProperty. Instead of creating a new ABMutableMultiValueRef for the phone numbers, copy it from the record like so:
ABMutableMultiValueRef phoneNumberMultiValue = ABMultiValueCreateMutableCopy((ABMultiValueRef)ABRecordCopyValue(contact, kABPersonPhoneProperty));
With this, you can now append the new phone number with the same code:
ABMultiValueAddValueAndLabel(phoneNumberMultiValue, phoneNum, kABPersonPhoneMobileLabel, NULL);
What's neat about this is that no replacing or deletion occurs - the app simply adds another phone number to the contact's phone numbers property. :D
Hope this helps.
The first thing you should do is pass in a reference to a CFErrorRef as the second argument to ABAddressBookSave; it may be that it's trying to report an error, but unable to, since you don't give it this argument.
Currently there is no way to EDIT and SAVE the contact to the address book. The IPhone API does not support this requirement. In order to EDIT a specific contact we need to get a reference of that contact by record ID and copy all the information to the reference and then save that contact to the address book.
I am showing an addressbook view to the user and letting them click on a contact and select a phone number. If they select a phone number, I want to get the phone number as an integer and the contact's name as an NSString.
I've tried doing it with the following code:
//printf("%s\n",[[(NSArray *)ABMultiValueCopyArrayOfAllValues(theProperty) objectAtIndex:identifier] UTF8String]);
//CFArrayRef *arrayString = [[(NSArray *)ABMultiValueCopyArrayOfAllValues(theProperty) objectAtIndex:identifier] UTF8String];
NSArray *arrayString = [(NSArray *)ABMultiValueCopyArrayOfAllValues(theProperty) objectAtIndex:identifier];
printf("%s\n", arrayString);
This code is inside this method:
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
And I am checking if the user selected a phone number with this code:
if (propertyType == kABStringPropertyType)
{
[self wrongSelection];
}
else if (propertyType == kABIntegerPropertyType)
{
[self wrongSelection];
}
else if (propertyType == kABRealPropertyType)
{
[self wrongSelection];
}
else if (propertyType == kABMultiStringPropertyType)
{
//This is the phone number...
I am able to get the phone number to display in the console with printf, however I can't figure out how to convert it into an integer and how to also get the contacts name even though the property selected is not a person's name.
Also, what I'm doing seems very inefficient. Are there any better ways to do this?
Edit: If I can't store them as an int, a string would be fine. I just can't figure out how to go from that array to an actual string. If I cast it or save it as a UTF8String I always get some error.
To get the property efficiently (as far as reading goes), you can do something like this in your callback method:
switch( propertyType ) {
case kABMultiStringPropertyType:
// this is the phone number, do something
break;
default:
[self wrongSelection];
break;
}
I'm not sure you actually even need to parse that, though. To get the phone number from the record you could do (again, inside your callback method):
ABMultiValueRef phoneNumberProperty = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSArray* phoneNumbers = (NSArray*)ABMultiValueCopyArrayOfAllValues(phoneNumberProperty);
CFRelease(phoneNUmberProperty);
// Do whatever you want with the phone numbers
NSLog(#"Phone numbers = %#", phoneNumbers);
[phoneNumbers release];
You can't convert the phone number into an integer. Phone numbers are strings. The default entry Apple includes for itself has the number "1-800-MYAPPLE".
Also, even if all components of a phone number are digits, there is no guarantee that phone numbers in all parts of the world are actually small enough to fit inside a 64 bit value, once you factor in area codes, country codes, internal extensions, etc. Users are free to put as much as they want in there.
Another reason not to use integers - some countries use leading zeros on phone numbers, e.g. all UK numbers start with a zero (usually written 01234 567890 or 0123 4567890)!
CFStringRef cfName = ABRecordCopyCompositeName(person);
NSString *personName = [NSString stringWithString:(NSString *)cfName];
CFRelease(cfName);
ABMultiValueRef container = ABRecordCopyValue(person, property);
CFStringRef contactData = ABMultiValueCopyValueAtIndex(container, identifier);
CFRelease(container);
NSString *contactString = [NSString stringWithString:(NSString *)contactData];
CFRelease(contactData);
contactString contains the phone number selected, and personName contains the person's name. As stated above, you can't necessarily convert the string to numbers generically, as it may contain alphabetic characters. However, you could write your own handler to convert alphabetic characters to numbers and strip out everything else to get a numeric string only, which you could then convert to a long (phone numbers get pretty long) .
I question the need to convert a phone number to a numeric value, though, since it may also contain other necessary characters like Pause. Also, a phone number represents a string of digits more than it represents one long number anyway, so the conceptual data format is more String than Int in any case.
Please be aware, that this code crashes in "stringWithString", if the Adressbook-Entry does not contain a name or a contacdata. cfName might be nil!
CFStringRef cfName = ABRecordCopyCompositeName(person);
NSString *personName = [NSString stringWithString:(NSString *)cfName];
CFRelease(cfName);
fix:
NSString *personName = nil;
if ((cfName = ABRecordCopyCompositeName(person)) != nil) {
personName = [NSString stringWithString:(NSString *)cfName];
CFRelease(cfName);
}