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."
Related
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
Some users have multiple address books in their iPhone Contacts, as a result of different synchronization connections they have made with e.g. Exchange Servers.
How is it possible to get all of these different address books? I would be interested in getting the names under which these different address books are saved and accessing their contact information.
Thank you!
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef sourcesArray = ABAddressBookCopyArrayOfAllSources(addressBook);
for (CFIndex i = 0; i < CFArrayGetCount(sourcesArray); i++) {
ABRecordRef source = (ABRecordRef)CFArrayGetValueAtIndex(sourcesArray, i);
ABRecordID sourceID = ABRecordGetRecordID(source);
CFNumberRef sourceType = (CFNumberRef)ABRecordCopyValue(source, kABSourceTypeProperty);
CFStringRef sourceName = (CFStringRef)ABRecordCopyValue(source, kABSourceNameProperty);
NSLog(#"source id=%d type=%d name=%#", sourceID, [(NSNumber *)sourceType intValue], sourceName);
CFRelease(sourceType);
if (sourceName != NULL) CFRelease(sourceName); // some source names are NULL
}
CFRelease(sourcesArray);
CFRelease(addressBook);
Note that, as of iOS 4, not all sources return a name. You may provide your own names based on type.
Use ABAddressBookCopyArrayOfAllPeopleInSource(addressBook, source) to get entries in a source.
There is only a single, centralized address book database on iOS accessible by a set of C functions, see ABAddressBook and the iOS address book programming guide.
You may be referring to groups within that address book. In that case, you can get the list of groups using the ABAddressBookCopyArrayOfAllGroups function as described in the reference on ABGroup.
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.
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.
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);
}