Sorting ABRecords alphabetically on iPhone - iphone

I'm retrieving contact names with this code:
for( int i = 0 ; i < n ; i++ )
{
Contact *c = [[Contact alloc] init];
ABRecordRef ref = CFArrayGetValueAtIndex(all, i);
NSString *firstName = (NSString *)ABRecordCopyValue(ref, kABPersonFirstNameProperty);
NSString *lastName = (NSString *)ABRecordCopyValue(ref, kABPersonLastNameProperty);
c.firstName = firstName; //[NSString stringWithFormat:#"%# %#", firstName, lastName];
c.lastName = lastName;
[contacts addObject:c];
[c release];
}
Does anyone know a way of ordering this list alphabetically? I've read about sortedArrayUsingSelector:#selector(compare:) but I have no idea how that is supposed to work.

NSSortDescriptor *mySorter = [[NSSortDescriptor alloc] initWithKey:#"lastName" ascending:YES];
[contacts sortUsingDescriptors:[NSArray arrayWithObject:mySorter]];
[mySorter release];

This method will let you respect the user's preferences for sorting by first or last name.
contacts = (bridgedPeople as [ABRecord]).sort {
(person1, person2) -> Bool in
return .CompareLessThan == ABPersonComparePeopleByName(person1, person2, ABPersonGetSortOrdering())
}
Pro-tip: Boldface the part of the name that you're sorting on; otherwise it gets confusing when you mix contacts who have [no first name, no last name, first and last name]

Related

fetching only mobile section record (not from iphone, home label etc) from addressbook?

How do I fetch only mobile section record from addressbook in ios?
I want to add only one record to my array that is fetched from mobile section record.
How do I do that. I am getting all the phone property records. but I need to get only mobile section record.
NSArray *allPeople = (NSArray *)ABAddressBookCopyArrayOfAllPeople(myAddressBook);
NSLog(#"allpeople%#", allPeople);
for (id record in allPeople) {
CFTypeRef phoneProperty = ABRecordCopyValue((ABRecordRef)record, kABPersonPhoneProperty);
NSArray *phones = (NSArray *)ABMultiValueCopyArrayOfAllValues(phoneProperty);
NSLog(#"phones %#",phones);
CFRelease(phoneProperty);
NSMutableDictionary *newRecord = [[NSMutableDictionary alloc] init];
NSMutableString *newPhone = [[NSMutableString alloc] init];
for (NSString *phone in phones) {
if(![newPhone isEqualToString:#""])
[newPhone appendString:#", "];
[newPhone appendString:phone];
}
You can try something like this..
ABMultiValueRef phoneNumbers = ABRecordCopyValue(abPerson, kABPersonPhoneProperty);
if (phoneNumbers) {
CFIndex numberOfPhoneNumbers = ABMultiValueGetCount(phoneNumbers);
for (CFIndex i = 0; i < numberOfPhoneNumbers; i++) {
NSString *phone = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phoneNumbers, i);
CFStringRef label = ABMultiValueCopyLabelAtIndex(phoneNumbers, i);
if (label) {
if (CFEqual(label, kABPersonPhoneMobileLabel)) {
primaryPhoneText.text = phone;
} else {
}
CFRelease(label);
[allPhones addObject:phone]; // allPhones is an array here.
}
}
CFRelease(phoneNumbers);
}
Hope this will help you out..
Enjoy coding..

checking whether the number is in phone contacts are not

i want to check whether the given number is in phone book or not programatically .
i am able to display the contact name of the given number if it is exists in phone book but the program crashes when there is no contact with that number in phone book ...
but what i want is to display name if it exists in phone book..... and display the number if if is not in phone book......
and my code is as follows....
NSMutableArray *names = [[NSMutableArray alloc] init];
NSMutableArray *phonenumbers = [[NSMutableArray alloc] init];
ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *thePeople = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
NSString *name;
for (id person in thePeople)
{
name = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSLog(#"!!!!!! name ---> %#",name);
ABMultiValueRef multi = ABRecordCopyValue(person, kABPersonPhoneProperty);
int count1=ABMultiValueGetCount(multi);
NSLog(#"%d",count1);
if ([name length]>0 && count1!=0)
{
NSString *beforenumber = (NSString *)ABMultiValueCopyValueAtIndex(multi, 0);
NSLog(#" contacts:%#",beforenumber );
NSString* removed1=[beforenumber stringByReplacingOccurrencesOfString:#"-"withString:#""];
NSString* removed2=[removed1 stringByReplacingOccurrencesOfString:#")"withString:#""];
NSString* removed3=[removed2 stringByReplacingOccurrencesOfString:#" "withString:#""];
NSString* removed4=[removed3 stringByReplacingOccurrencesOfString:#"("withString:#""];
NSString* removed5=[removed4 stringByReplacingOccurrencesOfString:#"+"withString:#""];
[names addObject:name];
[phonenumbers addObject:removed5];
}
}
int barindex = -1;
barindex = [phonenumbers indexOfObject:number];
if(barindex == -1)
return number;
else
return [names objectAtIndex:barindex];
can any one please help me how to do that.............
thank you.......
The code would be improved but I think that is what you need.
Sample Code

Search ABAddressbook iOS SDK

I want to search the iPhone address book for a specific phone number, and then retrieve the contact name. I am currently looping through all contacts and extracting the multivalue properties and comparing against the value. This is taking way too much time. I have read the Apple addressbook guide, and they say:
"accomplish other kinds of searches, use the function
ABAddressBookCopyArrayOfAllPeople and then filter the results using
the NSArray method filteredArrayUsingPredicate:."
Can anyone give me an example on how to exactly do that?
Thanks.
If you want to do a search in the contacts with phone number, then I will tell you one suggestion.
1.Get all contacts
NSArray *thePeoples = (NSArray*)ABAddressBookCopyArrayOfAllPeople(addressBook);
2.Create another array(records) from the contacts array(thePeoples),
records:[
record1, record2, ....recordN ]
record: {name:"myContactName",
phoneNumber:"1234567890"}
3.Search the mutableArray(records) with predicate.
NSPredicate * myPredicate = [NSPredicate predicateWithFormat:#"record.phoneNumber contains %#",string];
NSArray * filteredArray = [records filteredArrayUsingPredicate:myPredicate];
This is just a simple example to your solution, and remember phoneNumber is a multiValue field. So we will include an array as phone number in the model class variable.
The following method will return an array that contains all of the contacts that have the given phone number. This method took 0.02 seconds to search 250 contacts on my iPhone 5 running iOS7.
#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;
}
Use This. this is my code.
Make Array for searching.
NSLog(#"=====Make People Array with Numbers. Start.");
peopleWithNumber = [[NSMutableDictionary alloc] init];
for (int i=0; i < [people count]; i++) {
NSInteger phoneCount = [self phoneCountAtIndex:i];
if (phoneCount != 0) {
NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
for (int j=0 ; j < phoneCount ; j++) {
[phoneNumbers addObject:[self phoneNumberAtIndex:i phoneIndex:j]];
}
[peopleWithNumber addEntriesFromDictionary:
[NSDictionary dictionaryWithObjectsAndKeys:
[NSArray arrayWithArray:phoneNumbers], [self fullNameAtIndex:i], nil]];
}
}
NSLog(#"=====Make People Array with Numbers. End.\n");
Searching method. it(peopleWithNumber) would be faster than using array(people)
"NSArray *people = (NSArray *) ABAddressBookCopyArrayOfAllPeople(addressBook);"
- (NSArray *)searchNamesByNumber:(NSString *)number {
NSString *predicateString = [NSString stringWithFormat:#"%#[SELF] contains '%#'",#"%#",number];
NSPredicate *searchPredicate = [NSPredicate predicateWithFormat:predicateString,peopleWithNumber,number];
NSArray *names = [[peopleWithNumber allKeys] filteredArrayUsingPredicate:searchPredicate];
return names;
}
You cannot use a predicateWithFormat with an array of ABRecordRef opaque types. But you can use predicateWithBlock:
[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
ABRecordRef person=(__bridge ABRecordRef)evaluatedObject;
CFTypeRef theProperty = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSArray *phones = (__bridge_transfer NSArray *) ABMultiValueCopyArrayOfAllValues(theProperty);
CFRelease(theProperty);
BOOL result=NO;
for (NSString *value in phones) {
if ([value rangeOfString:#"3"].location!=NSNotFound) {
result=YES;
break;
}
}
return result;
}];

How to determine the type of an address in AddressBook FrameWork (iOS 4.2)

I´ve one big problem... I plan to write an app that deals with the users addressbook and it´s addresses. Everything´s fine - except the fact that I´m not able to determine whether the addesse´s type is "work", "home" or "other".
Does anybody know how to get the label for home, work and other?
Thanks in advance
Boris
This is the function I´m using at the moment:
+ (void)testing {
//Get the addressbook
ABAddressBookRef _addressBookRef = ABAddressBookCreate ();
//Fetch all contacts
NSArray* allPeople = (NSArray *)ABAddressBookCopyArrayOfAllPeople(_addressBookRef);
//Walk the contacts
for (id record in allPeople) {
//Get the contact´s id
NSInteger recordId = ABRecordGetRecordID((ABRecordRef)record);
//Get the contact´s name and company
NSString* recordName = (NSString *)ABRecordCopyCompositeName((ABRecordRef)record);
NSString* recordCompany = (NSString *)ABRecordCopyValue((ABRecordRef)record, kABPersonOrganizationProperty);
//Get the contact´s addresses
CFTypeRef adressesReference = ABRecordCopyValue((ABRecordRef)record, kABPersonAddressProperty);
NSArray *adressesArray = (NSArray *)ABMultiValueCopyArrayOfAllValues(adressesReference);
CFRelease(adressesReference);
NSLog(#"ID: %d", recordId);
NSLog(#"Name: %#", recordName);
NSLog(#"Firma: %#", recordCompany);
for (NSString *adress in adressesArray) {
NSLog(#"Adresse: %#", adress);
}
[adressesArray release];
}
CFRelease(_addressBookRef);
[allPeople release];
NSLog(#"\n");
}
And here´s the log output:
ID: 1
Name: The first user
Firma: (null)
Adresse: {
City = Reutlingen;
Country = Germany;
CountryCode = de;
Street = "some street";
ZIP = 23456;
}
Adresse: {
City = Reutlingen;
Country = Germany;
CountryCode = de;
State = BW;
Street = "Street number 2";
ZIP = 98765;
}
ID: 2
Name: The second contact
Firma: Firma
Adresse: {
Country = "United States";
CountryCode = us;
Street = Test;
}
here is how you get the address book values extracted:
ABMultiValueRef addresses = ABRecordCopyValue(ref, kABPersonAddressProperty);
for (CFIndex j = 0; j<ABMultiValueGetCount(addresses);j++){
CFDictionaryRef dict = ABMultiValueCopyValueAtIndex(addresses, j);
CFStringRef typeTmp = ABMultiValueCopyLabelAtIndex(addreses, j);
CFStringRef labeltype = ABAddressBookCopyLocalizedLabel(typeTmp);
NSString *street = [(NSString *)CFDictionaryGetValue(dict, kABPersonAddressStreetKey) copy];
NSString *city = [(NSString *)CFDictionaryGetValue(dict, kABPersonAddressCityKey) copy];
NSString *state = [(NSString *)CFDictionaryGetValue(dict, kABPersonAddressStateKey) copy];
NSString *zip = [(NSString *)CFDictionaryGetValue(dict, kABPersonAddressZIPKey) copy];
NSString *country = [(NSString *)CFDictionaryGetValue(dict, kABPersonAddressCountryKey) copy];
[street release];
[city release];
[state release];
[zip release];
[country release];
CFRelease(dict);
CFRelease(type);
CFRelease(typeTmp);
}
CFRelease(addresses);
the label type is what you are looking for.
good luck
shani

iPhone SDK Accessing Address book company contact

I have been able to use the SDK to access Address Book contacts for people, but whenever I pick a contact who is a company, my app crashes.
does anyone know the property for the company field?
does anyone know the code to make it work?
thanks in advance
It seems your issue is not related to company tag itself. AB fields need to be managed carefully, released when not used and checked for nil all the time, many fields are not set.
In principle, here is example of how I use it. This function loads contacts (those fields interested for my app) and returns array with contacts to the caller. Hope this is helpful. Note how I release not needed refs.
- (NSArray *)loadContacts
{
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
NSMutableArray *contacts = [NSMutableArray array];
for (int i = 0 ; i < nPeople ; i++ ) {
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i);
NSString *firstName = ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSString *lastName = ABRecordCopyValue(person, kABPersonLastNameProperty);
NSString *fullName;
if (firstName && lastName) {
fullName = [NSString stringWithFormat:#"%# %#", firstName, lastName];
} else {
if (firstName) {
fullName = [NSString stringWithString:firstName];
} else if (lastName) {
fullName = [NSString stringWithString:lastName];
} else {
continue;
}
}
NSString *email = nil;
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
if (emails) {
NSArray *emailAddresses = [(NSArray *)ABMultiValueCopyArrayOfAllValues(emails) autorelease];
if (emailAddresses && [emailAddresses count] > 0)
email = [emailAddresses objectAtIndex:0];
CFRelease(emails);
}
if (email) {
NSDictionary *contact = [NSDictionary
dictionaryWithObjectsAndKeys:fullName, #"name",
email, #"email", nil];
[contacts addObject:contact];
}
if (firstName)
CFRelease(firstName);
if (lastName)
CFRelease(lastName);
}
CFRelease(allPeople);
CFRelease(addressBook);
return contacts;
}
you need to use kABPersonOrganizationProperty property for get the company name from addressbook