Access a specific ABAddressbook Group - ios

I am using
NSMutableArray *people = [[[(NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook) autorelease] mutableCopy] autorelease];
to access the Addressbook.
Now I want to access a specific Addressbook Group from an Exchange Server.
Is this possible?

You will need to do not something like this.
ABRecordRef exchange = ABAddressBookGetSourceWithRecordID(addressBook, kABSourceTypeExchange);
CFArrayRef groups = ABAddressBookCopyArrayOfAllGroupsInSource(addressBook, exchange);
CFArrayRef officePersonnel;
for (ABRecordRef group in (NSArray *)groups) {
CFStringRef groupName = ABRecordCopyValue(group, kABGroupNameProperty, NULL);
if ( CFStringFind(groupName, CFSTR("Office"), kCFCompareCaseInsensitive) != kCFNotFound ) {
officePersonnel = ABGroupCopyArrayOfAllMembers(group);
}
CFRelease(groupName);
}
CFRelease(groups);
// Use and later release `officePersonnel`

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;
}

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

iOS can't get person's image

I have two tableViewControllers. The first one has a list of contacts. The another one shows detailed person's information.
A chunk of code of first tableViewController
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef source = ABAddressBookCopyDefaultSource(addressBook);
NSArray *allPeople = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, source,kABPersonSortByFirstName);
for ( int i = 0; i < [allPeople count]; i++ )
{
...
contactClass = [[ContactClass alloc] initWithName:name surName:surName manID:[allPeople objectAtIndex:i]];
...
}
A chunck of code of second tableViewController
ABRecordRef person = (__bridge ABRecordRef)contactClass.manID;
BOOL isHasImage = ABPersonHasImageData(person);
Variable isHasImage is always false, even if contact has an avatar. I even checked this on the first tableViewController and if person has an avatar, then it returns true and image.
Does anyone knows why I can't get contacts image?
p.s. contactClass.manID is type of id. It has a correct adress, because ABMultiValueRef multiValue = ABRecordCopyValue((__bridge ABRecordRef)contactClass.manID, kABPersonPhoneProperty); returns correct value in the second tableViewController
I may be too late for a solution for you, but maybe this will help others that are stuck with the same problem.
Looks like ABPersonHasImageData() and ABPersonCopyImageDataWithFormat() don't work as expected on ABRecordRef copies (e.g. an ABContactRef from an array obtained using ABAddressBookCopyArrayOfAllPeople()), at leas on iOS 5.x. You may workaround it like this:
- (UIImage*)imageForContact: (ABRecordRef)contactRef {
UIImage *img = nil;
// can't get image from a ABRecordRef copy
ABRecordID contactID = ABRecordGetRecordID(contactRef);
ABAddressBookRef addressBook = ABAddressBookCreate();
ABRecordRef origContactRef = ABAddressBookGetPersonWithRecordID(addressBook, contactID);
if (ABPersonHasImageData(origContactRef)) {
NSData *imgData = (NSData*)ABPersonCopyImageDataWithFormat(origContactRef, kABPersonImageFormatOriginalSize);
img = [UIImage imageWithData: imgData];
[imgData release];
}
CFRelease(addressBook);
return img;
}
Any further update on this ?
I have received complaints for some user not able to see thumbnail for a few contacts. Mostly it works fine, Is there any special case in which thumbnails aren't returned.
I am using the following piece of code:
- (instancetype)initWithABContact:(ABRecordRef)contact {
NSData *iThumbnailData = nil;
if (ABPersonHasImageData(contact)) {
iThumbnailData =
CFBridgingRelease(ABPersonCopyImageDataWithFormat(contact, kABPersonImageFormatThumbnail));
}
}

AddressBook ABPerson Twitter Social Profile

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]];
}
}

How to use ABUnknownPersonViewController with generated data entered intially?

This is very specific case. I believe someone had already solved this somewhere, but it's not easy for me to find it.
The situation:
1 ) an object will return NSString objects for name address1, address2, phone:
[anObject name];
[anObject address1];
[anObject address2];
[anObject name];
2 ) I would like to use these objects to prepare ABUnknownPersonViewController with initially entered values, so the user will not have to enter them before saving them in Address Book.
I have looked at iOS documents and searched through Google and StackOverflow, can't find the right answer for this simple situation.
Can anyone guide me on this?
Found an answer: It's nicely documented in iOS Developer Library:
http://developer.apple.com/library/ios/#samplecode/QuickContacts/Listings/Classes_QuickContactsViewController_m.html#//apple_ref/doc/uid/DTS40009475-Classes_QuickContactsViewController_m-DontLinkElementID_6
Here is a sample code I implemented to return a ABPersonRecordRef as an object. The error I had experienced was related to not retaining the ABPersonRecordRef object after returning it.
- (id)personRecordUsingModelObj:(id)modelObj {
ABRecordRef aContact = ABPersonCreate();
CFErrorRef anError = NULL;
NSString *name = [NSString stringWithFormat:#"%#", [modelObj name]];
ABRecordSetValue(aContact, kABPersonOrganizationProperty, name, &anError);
ABMultiValueRef phone = ABMultiValueCreateMutable(kABMultiStringPropertyType);
ABMultiValueAddValueAndLabel(phone, [modelObj phone], kABPersonPhoneMainLabel, NULL);
ABRecordSetValue(aContact, kABPersonPhoneProperty, phone, &anError);
CFRelease(phone);
NSString *address = [NSString stringWithFormat:#"%# %#", [modelObj addr1], [modelObj addr2]];
NSMutableDictionary *dictionaryAddress = [[NSMutableDictionary alloc] initWithCapacity:0];
[dictionaryAddress setObject:address forKey:(NSString *)kABPersonAddressStreetKey];
[dictionaryAddress setObject:#"us" forKey:(NSString *)kABPersonAddressCountryCodeKey];
ABMutableMultiValueRef address = ABMultiValueCreateMutable(kABDictionaryPropertyType);
ABMultiValueAddValueAndLabel(address, dictionaryAddress, kABPersonAddressStreetKey, NULL);
[dictionaryAddress release];
ABRecordSetValue(aContact, kABPersonAddressProperty, address, &anError);
CFRelease(address);
if (anError) {
aContact = nil;
}
[(id)aContact autorelease];
return (id)aContact;
}

Resources