AddressBook ABPerson Twitter Social Profile - ios

Have you ever tried to get data fields from the address book and ran into the wonderful world of ABPerson reference only to find it reads like the blueprints to a space rocket?
I've gotten so far but I still need help getting just the Twitter username key & value:
//I tried this but I can't seem to get the if statement to work
ABMutableMultiValueRef socialMulti = ABRecordCopyValue(person, kABPersonSocialProfileProperty);
NSMutableDictionary *mySocialDict = [NSMutableDictionary dictionaryWithCapacity:ABMultiValueGetCount(socialMulti)];
NSLog(#"entering social dict of count %ld", ABMultiValueGetCount(socialMulti));
for (CFIndex i = 0; i < ABMultiValueGetCount(socialMulti); i++) { 
CFStringRef socialLabel = ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(socialMulti, i));
CFStringRef social = ABMultiValueCopyValueAtIndex(socialMulti, i); 
if ([(__bridge NSString*)socialLabel isEqualToString:#"twitter"]) {
NSLog(#"we got a twitter");
}
[mySocialDict setObject:(__bridge NSString*)social forKey:(__bridge NSString*)socialLabel];
NSLog(#"social is %#",social);
CFRelease(social);
CFRelease(socialLabel);
}
 
I'm actually just interested in the twitter username. I know I could get it from the dictionary I created but I want to get it directly. I plan to eliminate the NSDictionary step anyway.

Here's an excerpt from my code. Replace your var names as necessary.
ABMultiValueRef socialMulti = ABRecordCopyValue(recordRef, kABPersonSocialProfileProperty);
NSMutableArray* twitterHandlesArray = [[NSMutableArray alloc] initWithCapacity:ABMultiValueGetCount(socialMulti)];
for (CFIndex i = 0; i < ABMultiValueGetCount(socialMulti); i++) {
NSDictionary* social = (__bridge NSDictionary*)ABMultiValueCopyValueAtIndex(socialMulti, i);
if ([social[#"service"] isEqualToString:(__bridge NSString*)kABPersonSocialProfileServiceTwitter]) {
NSString* username = (NSString*)social[#"username"];
NSLog(#"we got a twitter. username is %#", username);
[twitterHandlesArray addObject:[[username conditionedAsTwitterHandle] SHA2Digest]];
}
}

Related

find ios ABRecordRef contact in AddressBook by phone, email, name

I need to find a contact in AdreesBook in order to add a new social network.
Sometimes I have to find a contact by its phones and emails or by its phones, firstName and lastName, is there any kind of query to get ABRecordRef contact instead of doing whiles?
Many of my users have more than 1000 contacts and I need to update many of them, so it is not efficient if my only solution is to do so many whiles...
Any idea??
Thanks!
Below is method which may help you to get the Contact details using phone number. For that its used kABPersonPhoneProperty, same way you can write another functions for searching email and name:
For email, use a property : kABPersonEmailProperty
For First Name : kABPersonFirstNameProperty
For more details, go through: ABPerson Reference
Hope this helps.
#import <AddressBook/AddressBook.h>
-(NSArray *)contactsContainingPhoneNumber:(NSString *)phoneNumber {
/*
Returns an array of contacts that contain the phone number
*/
// Remove non numeric characters from the phone number
phoneNumber = [[phoneNumber componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]] componentsJoinedByString:#""];
// Create a new address book object with data from the Address Book database
CFErrorRef error = nil;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
if (!addressBook) {
return [NSArray array];
} else if (error) {
CFRelease(addressBook);
return [NSArray array];
}
// Requests access to address book data from the user
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {});
// Build a predicate that searches for contacts that contain the phone number
NSPredicate *predicate = [NSPredicate predicateWithBlock: ^(id record, NSDictionary *bindings) {
ABMultiValueRef phoneNumbers = ABRecordCopyValue( (__bridge ABRecordRef)record, kABPersonPhoneProperty);
BOOL result = NO;
for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
NSString *contactPhoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
contactPhoneNumber = [[contactPhoneNumber componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]] componentsJoinedByString:#""];
if ([contactPhoneNumber rangeOfString:phoneNumber].location != NSNotFound) {
result = YES;
break;
}
}
CFRelease(phoneNumbers);
return result;
}];
// Search the users contacts for contacts that contain the phone number
NSArray *allPeople = (NSArray *)CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
NSArray *filteredContacts = [allPeople filteredArrayUsingPredicate:predicate];
CFRelease(addressBook);
return filteredContacts;
}

How do I get Facebook and custom social addresses from iOS address book?

In my peoplePickerNavigationController:shouldContinueAfterSelectingPerson I'm able to read a bunch of the iOS Contacts info from the chosen contact into my app.
The one item I can't figure out how to read is the Facebook (and other social) address info. Here's what I've got and I know it's not quite right. The problem has something to do with the label I think:
ABMultiValueRef socialRef = ABRecordCopyValue(person, kABPersonSocialProfileProperty);
for (int i = 0; i < ABMultiValueGetCount(socialRef); i++) {
CFStringRef currentSocialLabel = ABMultiValueCopyLabelAtIndex(socialRef, i);
CFStringRef currentSocialValue = ABMultiValueCopyValueAtIndex(socialRef, i);
if (CFStringCompare(currentSocialLabel, kABPersonSocialProfileServiceFacebook, 0) == kCFCompareEqualTo) {
[theContactInfoDictionary setObject:(__bridge NSString *)currentSocialValue forKey:#"theFacebook"];
}
CFRelease(currentSocialLabel);
CFRelease(currentSocialValue);
}
CFRelease(socialRef);
Please point me in the right direction.
Furthermore, I also need to check if there is a custom social entry for "Google+" (my app can create these entries in another place) and if there is, I want to import that value as well. How do I go about doing this?
Thanks!
sigh
And I figured it out. Here's what I did:
ABMultiValueRef socialRef = ABRecordCopyValue(person, kABPersonSocialProfileProperty);
for (int i = 0; i < ABMultiValueGetCount(socialRef); i++) {
NSDictionary *socialDictionary = (__bridge NSDictionary *)ABMultiValueCopyValueAtIndex(socialRef, i);
if ([socialDictionary[#"service"] isEqualToString:(__bridge NSString *)kABPersonSocialProfileServiceFacebook]) {
[theContactInfoDictionary setObject:(NSString *)socialDictionary[#"username"] forKey:#"theFacebook"];
} else if ([socialDictionary[#"service"] isEqualToString:(__bridge NSString *)kABPersonSocialProfileServiceTwitter]) {
[theContactInfoDictionary setObject:(NSString *)socialDictionary[#"username"] forKey:#"theTwitter"];
} else if ([socialDictionary[#"service"] isEqualToString:#"Google+"]) {
[theContactInfoDictionary setObject:(NSString *)socialDictionary[#"username"] forKey:#"theGoogle"];
}
}
CFRelease(socialRef);

Copy contacts phone numbers to array using ABAdressPhoneBookRef

I think I need to use ABMultiValueCopyArrayOfAllValues to grab all phone numbers from my ABAddressBookRef reference variable.
(If this is not the correct way to do it, please give me a correct way; ANY way that gives me access to contact phone numbers will do)
What I'd like to do now, is grab my user's contact's phone numbers(preferably their cell) and add that to an array.
How do I grab just the numbers and add that to an array?
Any help, suggestions, or advice with this is greatly appreciated in advice, I'm not finding this anywhere.
Thanks.
If I were you, I would use this approach:
NSMutableArray *allPhoneNumbers = #[].mutableCopy;
NSArray *allContact = (__bridge NSArray*)ABAddressBookCopyArrayOfAllPeople(book);
for (id rec in allContacts){
ABMultiValueRef mvr = ABRecordCopyValue((__bridge ABRecordRef)rec, kABPersonPhoneProperty);
NSArray *currentNums = (__bridge NSArray*) ABMultiValueCopyArrayOfAllValues(mvr);
[allPhoneNumbers addObjectsFromArray: currentNums];
}
I have not tested this, but it should work. Tell me if you have any issues.
If you want just one contact's numbers (the above gets every contact), use this code.
ABMultiValueRef mvr = ABRecordCopyValue(yourRecordRef, kABPersonPhoneProperty);
NSArray *currentNums = (__bridge NSArray*) ABMultiValueCopyArrayOfAllValues(mvr);
[allPhoneNumbers addObjectsFromArray: currentNums];
ABMultiValueRef phoneNumbers = ABRecordCopyValue(ref, kABPersonPhoneProperty);
for(CFIndex j = 0; j < ABMultiValueGetCount(phoneNumbers); j++)
{
CFStringRef phoneNumberRefCF = ABMultiValueCopyValueAtIndex(phoneNumbers, j);
CFStringRef locLabelCF = ABMultiValueCopyLabelAtIndex(phoneNumbers, j);
NSString *phoneLabelCF =(NSString*) ABAddressBookCopyLocalizedLabel(locLabelCF);
NSString *phoneNumberCF = (NSString *)phoneNumberRefCF;
CFRelease(phoneNumberRefCF);
CFRelease(locLabelCF);
NSLog(#" - %# (%#)", phoneNumberCF, phoneLabelCF);
}

ABAddressBook -- Search Exchange AddressBook Source?

I'm trying to create an app with a custom interface for searching through one's addressbook. Searching the local addressbook seems easy, but I cannot figure out how to search for a person/record in an Exchange addressbook source (i.e. ABSourceType == kABSourceTypeExchangeGAL). I'm using the following code to find the Exchange addressbook source and query it, but I only ever get back an empty array. I understand asking for the entire list of people in an Exchange addressbook cannot possibly return all entries, but I would expect some subset of that list when I query it. Again, instead I get an empty array.
How do you search for contacts in an Exchange addressbook source?
#define CFNIL(x) if(x){CFRelease(x); x=nil;}
//code
ABAddressBookRef _addressbook = ABAddressBookCreate();
CFArrayRef allSources = ABAddressBookCopyArrayOfAllSources(_addressbook);
ABRecordRef exchangeSource;
for(CFIndex i =0; i<CFArrayGetCount(allSources); i++)
{
ABRecordRef source = (ABRecordRef)CFArrayGetValueAtIndex(allSources, i);
NSNumber *sourceTypeNumber = (NSNumber*)((CFNumberRef)ABRecordCopyValue(source, kABSourceType));
NSString *sourceTypeName = (NSString *)((CFStringRef)ABRecordCopyValue(source, kABSourceNameProperty));
int sourceType = [sourceTypeNumber intValue];
if (sourceType == kABSourceTypeExchangeGAL)
{
exchangeSource = source;
}
[sourceTypeNumber release];
[sourceTypeName release];
}
if(exchangeSource)
{
/*
This finds matches in the local device addressbook
NSArray *people = (NSArray *)ABAddressBookCopyPeopleWithName(_addressbook, CFSTR("joe"));
for(int i=0;i<[people count]; i++)
{
ABRecordRef person = (ABRecordRef)[people objectAtIndex:i];
ABMultiValueRef emails = (ABMultiValueRef)ABRecordCopyValue(person, kABPersonEmailProperty);
NSLog(#"emails: %#",emails);
[((NSArray*)emails) release];
}
[people release];
*/
//this array is always empty
CFArrayRef search = ABAddressBookCopyArrayOfAllPeopleInSource (_addressbook,exchangeSource);
NSLog(#"%#", search);
CFNIL(search);
}
CFNIL(exchangeSource);
CFNIL(_addressbook);

Question regarding errand on UITableView creation from iPhone Addressbook

I have a question regarding the AddressBook Framework for iOS. The situation is as follows:
I'm trying recreate the contacts view from the phone application, but I want to show the contact's phone numbers in the same view. So if a contact has more than one number, his name will be in the TableView multiple times, each time with a different number.
I am trying to accomplish that by extracting all the information I need when the view loads and after that, populate the TableView with the appropriate values from an NSArray consisting of NSDictionaries containing the contact's information.
This works great except for one thing... The contact's phonenumbers and labels are read correctly and stored in the dictionary, but when I read them out later, they seem to have vanished.
Here's my code for generating the NSDictionaries, I bet it's some kind of memory management error or something completly stupid. I hope anyone can help me, thanks a lot in advance!
persons = [[NSMutableArray alloc] init];
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
NSArray *people = (NSArray *)ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source, kABPersonSortByLastName);
for (id record in people)
{
ABMultiValueRef numbers = ABRecordCopyValue((ABRecordRef)record, kABPersonPhoneProperty);
for (CFIndex i = 0; i < ABMultiValueGetCount(numbers); ++i) {
CFStringRef label = ABAddressBookCopyLocalizedLabel(ABMultiValueCopyLabelAtIndex(numbers, i));
CFStringRef number = ABMultiValueCopyValueAtIndex(numbers, i);
CFStringRef firstNameRef = ABRecordCopyValue((ABRecordRef)record, kABPersonFirstNameProperty);
CFStringRef lastNameRef = ABRecordCopyValue((ABRecordRef)record, kABPersonLastNameProperty);
CFDataRef imageDataRef = ABPersonCopyImageDataWithFormat((ABRecordRef)record, kABPersonImageFormatThumbnail);
NSString *firstName = [NSString stringWithFormat:#"%#", firstNameRef];
NSString *lastName = [NSString stringWithFormat:#"%#", lastNameRef];
NSString *pLabel = [[NSString alloc] initWithFormat:#"%#", label];
NSString *pNumber = [NSString stringWithFormat:#"%#", number];
UIImage *image = [UIImage imageWithData:(NSData*)imageDataRef];
NSDictionary *personDict = [NSDictionary dictionaryWithObjectsAndKeys:firstName, #"firstName", lastName, #"lastName", image, #"image", pNumber, #"phoneNumber", pLabel, #"label", nil];
NSLog(#"In %# - %#", pLabel, pNumber);
[persons addObject:personDict];
CFRelease(firstNameRef);
CFRelease(lastNameRef);
//CFRelease(imageDataRef);
CFRelease(label);
CFRelease(number);
}
}
CFRelease(addressBook);
CFRelease(source);
[people release];
Finally could resolve this myself. Apparently I was adding some nil-images to the dictionaries which they couldn't handle.

Resources