I've been looking the web for this solution. Its exactly like the google maps application on the iphone, where as you search, it looks through the address book to find suggestions for what your looking for.
What i managed to do so far is set up a search bar and a mapview, so when i search for the exact address i get it displayed on the map.
I want to make it easier for the users, who might have addresses stored in their address book to use it to search on the map view.
I know that you need to use search display controller and address book, but i can't find any examples of search display controller on other than a default table view.
this is what i have so far
EDIT.
I guess no one knows. But it took me a couple of days to figure it out.
Heres the solution for everyone wanting to learn how to do this.
The key thing to know here is how to get the address book data into an array that you can just use with the search display controller to filter it out.
So here is the method i came up with to get the address book data:
- (void) getContactData
{
NSMutableDictionary *myAddressBook = [[NSMutableDictionary alloc] init];
self.names = [NSMutableArray array];
ABAddressBookRef addressBook = ABAddressBookCreate();
if (addressBook != nil){
NSLog(#"Successfully accessed the address book.");
NSArray *allPeople = (__bridge_transfer NSArray *) ABAddressBookCopyArrayOfAllPeople(addressBook);
NSString *address;
NSUInteger peopleCounter = 0;
for (peopleCounter = 0;
peopleCounter < [allPeople count]; peopleCounter++){
ABRecordRef thisPerson = (__bridge ABRecordRef)
[allPeople objectAtIndex:peopleCounter];
NSString *firstName = (__bridge_transfer NSString *) ABRecordCopyValue(thisPerson, kABPersonFirstNameProperty);
NSString *lastName = (__bridge_transfer NSString *) ABRecordCopyValue(thisPerson, kABPersonLastNameProperty);
NSString *company = (__bridge_transfer NSString *) ABRecordCopyValue(thisPerson, kABPersonOrganizationProperty);
ABMutableMultiValueRef multiValue = ABRecordCopyValue(thisPerson, kABPersonAddressProperty);
for(CFIndex i=0;i<ABMultiValueGetCount(multiValue);i++)
{
NSString* HomeLabel = (__bridge NSString*)ABMultiValueCopyLabelAtIndex(multiValue, i);
if([HomeLabel isEqualToString:#"_$!<Home>!$_"])
{
CFDictionaryRef dict = ABMultiValueCopyValueAtIndex(multiValue, i);
CFStringRef street = CFDictionaryGetValue(dict, kABPersonAddressStreetKey);
CFStringRef city = CFDictionaryGetValue(dict, kABPersonAddressCityKey);
CFStringRef state = CFDictionaryGetValue(dict, kABPersonAddressStateKey);
CFStringRef zip = CFDictionaryGetValue(dict, kABPersonAddressZIPKey);
CFRelease(dict);
if (zip == nil) {
address = [NSString stringWithFormat:#"%#, %#, %# ", street, city, state];
}else {
address = [NSString stringWithFormat:#"%#, %#, %# , %#", street, city, state, zip];
}
}
if ([address length] != 0) {
// [self.addresses insertObject:address atIndex:i];
[myAddressBook setObject:address forKey:#"Address"];
if ([firstName length] != 0 && [lastName length] != 0) {
NSString *name= [NSString stringWithFormat: #"%# %#", firstName, lastName];
[myAddressBook setObject:name forKey:#"Name"];
// [names insertObject:name atIndex:i];
}
else if ([firstName length] != 0 && [lastName length] == 0) {
NSString *name= [NSString stringWithFormat: #"%#", firstName];
// [names insertObject:name atIndex:i];
[myAddressBook setObject:name forKey:#"Name"];
}
else if ([firstName length] == 0 && [lastName length] == 0) {
if ([company length] != 0) {
//[names insertObject:company atIndex:i];
[myAddressBook setObject:company forKey:#"Name"];
}
}
NSString *name = [myAddressBook objectForKey:#"Name"];
NSString *address = [myAddressBook objectForKey:#"Address"];
NSDictionary* personDict = [[NSDictionary alloc] initWithObjectsAndKeys:name,#"Name",address,#"Address",nil];
[self.names addObject:personDict];
}
}
}
CFRelease(addressBook);
}
}
// Setup SearchBar
UISearchBar *search = [[UISearchBar alloc] initWithFrame:CGRectMake(20, 0, 278, 44)];
search.delegate = self;
self.searchBar = search;
// Setup Map View
MKMapView *mapView = [[MKMapView alloc] initWithFrame:CGRectMake(20, 44, 278, 150)];
mapView.mapType = MKMapTypeStandard;
mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.myMapview = mapView;
[self.view addSubview:self.myMapview];
[self.view addSubview:self.searchBar];
- (void)searchBarSearchButtonClicked:(UISearchBar *)aSearchBar {
// When the search button is tapped, add the search term to recents and conduct the search.
NSString *searchString = [searchBar text];
self.eventLocationCoordinate = [self getLocationFromAddressString:searchString];
[self zoomMapAndCenterAtLatitude:self.eventLocationCoordinate.latitude andLongitude:self.eventLocationCoordinate.longitude];
[self setMapAnnotationAtCoordinate:self.eventLocationCoordinate withTitle:#"Your Here" andSubtitle:searchString];
}
Have fun coding!
Related
Right now i am using the <AddressBookUI/AddressBookUI.h>
it is working fine, it is opening the address view controller, after tapping in a contact it goes to the detail view where I can click on any property to select and get the information.
below is the code i am using right now:
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {
[self peoplePickerNavigationController:peoplePicker shouldContinueAfterSelectingPerson:person property:property identifier:identifier]; }
- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker {
[picker dismissModalViewControllerAnimated:YES]; }
- (BOOL)peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property
identifier:(ABMultiValueIdentifier)identifier
{
ABMutableMultiValueRef multi = ABRecordCopyValue(person, property);
CFStringRef phone1 = ABMultiValueCopyValueAtIndex(multi, identifier);
NSLog(#"phone %#", (__bridge NSString *)phone1);
CFRelease(phone1);
ABMultiValueRef fnameProperty = ABRecordCopyValue(person, kABPersonFirstNameProperty);
ABMultiValueRef lnameProperty = ABRecordCopyValue(person, kABPersonLastNameProperty);
ABMultiValueRef phoneProperty = ABRecordCopyValue(person, kABPersonPhoneProperty);
ABMultiValueRef emailProperty = ABRecordCopyValue(person, kABPersonEmailProperty);
NSArray *emailArray = (__bridge NSArray *)ABMultiValueCopyArrayOfAllValues(emailProperty);
NSArray *phoneArray = (__bridge NSArray *)ABMultiValueCopyArrayOfAllValues(phoneProperty);
NSString *name,*phone,*email;
phone = [[NSString alloc]init];
email = [[NSString alloc]init];
name = [[NSString alloc]init];
if (fnameProperty != nil) {
name = [NSString stringWithFormat:#"%#", fnameProperty];
}
if (lnameProperty != nil) {
name = [name stringByAppendingString:[NSString stringWithFormat:#" %#", lnameProperty]];
}
if ([phoneArray count] > 0) {
if ([phoneArray count] > 1) {
for (int i = 0; i < [phoneArray count]; i++) {
phone = [phone stringByAppendingString:[NSString stringWithFormat:#"%#,", [phoneArray objectAtIndex:i]]];
}
}else {
phone = [NSString stringWithFormat:#"%#", [phoneArray objectAtIndex:0]];
}
}
if ([emailArray count] > 0) {
if ([emailArray count] > 1) {
for (int i = 0; i < [emailArray count]; i++) {
email = [email stringByAppendingString:[NSString stringWithFormat:#"%#\n", [emailArray objectAtIndex:i]]];
}
}else {
email = [NSString stringWithFormat:#"%#", [emailArray objectAtIndex:0]];
}
}
//----setting txt field values
NSArray *f_name = [name componentsSeparatedByString:#" "];
if(f_name.count>1)
{
txtFirstname.text = [f_name objectAtIndex:0];
txtLastname.text = [f_name objectAtIndex:1];
}else{
txtFirstname.text = [f_name objectAtIndex:0];
}
NSArray *only_1_no = [phone componentsSeparatedByString:#","];
NSString *str = [only_1_no objectAtIndex:identifier];
NSCharacterSet *unwantedStr = [NSCharacterSet characterSetWithCharactersInString:#"+() -"];
str = [[str componentsSeparatedByCharactersInSet: unwantedStr] componentsJoinedByString: #""];
NSArray *ar = [email componentsSeparatedByString:#"\n"];
NSMutableString *abcd = [[NSMutableString alloc]init];
for (int i = 0; i<str.length; i++)
{
NSString *abc = [NSString stringWithFormat:#"%C",[phone characterAtIndex:i]];
if(i==0){
abcd =[NSMutableString stringWithFormat:#"%#",abc];
}else{
abcd = [NSMutableString stringWithFormat:#"%#%#",abcd,abc];
}
[self showmaskonnumber:abcd];
}
txtPhoneno.text = str;
txtEmail.text = [ar objectAtIndex:0];
ABPeoplePickerNavigationController *peoplePicker1 = (ABPeoplePickerNavigationController *)peoplePicker.navigationController;
[peoplePicker1 dismissModalViewControllerAnimated:YES];
[txtEmail becomeFirstResponder];
return YES;
}
my question is: Which changes should I make to this code so when I select a contact on the address list view, the selection returns the contact and all its information without showing its details?
I solved my issue by using this delegate method
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker didSelectPerson:(ABRecordRef)person;
{ [self selectedPerson:person]; }
I am using SQLite and I want to save the name, address, and phone text fields for them to show up in the next view controller for when the "show details" button is clicked in 1st VC.
I placed "save" and "show details" button in 1st VC, as well as "previous" and "next" button in 2nd VC. Whenever I click on "show details" I am getting this error message:
index 0 beyond bounds for empty array.
However, I see that the array is not empty. I want to store the student details in the array.
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *homeDirectory = NSHomeDirectory();
NSString *documentsDirectoryPath = [homeDirectory stringByAppendingPathComponent:#"Documents"];
self.dbFilePathInDocuments = [documentsDirectoryPath stringByAppendingPathComponent:#"details.db"];
self.studentDetails = [[NSMutableArray alloc]init];
NSString *selectQuery = [NSString stringWithFormat:#"select name,address,phone from contacts"];
sqlite3_open([self.dbFilePathInDocuments UTF8String], &dataBase);
sqlite3_prepare_v2(dataBase, [selectQuery UTF8String], -1,&selectStatement, NULL);
while (sqlite3_step(selectStatement) == SQLITE_ROW)
{
NSMutableDictionary *studentDict = [[NSMutableDictionary alloc]init];
NSString *name = [NSString stringWithFormat:#"%s",sqlite3_column_text(selectStatement, 0)];
NSString *address = [NSString stringWithFormat:#"%s",sqlite3_column_text(selectStatement, 1)];
NSString *phone = [NSString stringWithFormat:#"%s",sqlite3_column_text(selectStatement, 2)];
[studentDict setObject:name forKey:#"name"];
[studentDict setObject:address forKey:#"address"];
[studentDict setObject:phone forKey:#"phone"];
[self.studentDetails addObject:studentDict];
NSLog(#"student is:%#",self.studentDetails);
}
sqlite3_finalize(selectStatement);
sqlite3_close(dataBase);
self.nameLabel.text = [[self.studentDetails objectAtIndex:0] valueForKey:#"name"];
self.addressLabel.text = [[self.studentDetails objectAtIndex:0] valueForKey:#"address"];
self.phoneLabel.text = [[self.studentDetails objectAtIndex:0] valueForKey:#"phone"];
currentStudentIndex = 0;
}
- (IBAction)clickPrevious:(id)sender {
if(currentStudentIndex <=0)
{
currentStudentIndex = 0;
}else
{
currentStudentIndex = currentStudentIndex - 1;
}
self.nameLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"name"];
self.addressLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"address"];
self.phoneLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"phone"];
}
- (IBAction)clickNext:(id)sender {
if(currentStudentIndex >= [self.studentDetails count] - 1)
{
currentStudentIndex = [self.studentDetails count] - 1;
}else
{
currentStudentIndex = currentStudentIndex + 1;
}
self.nameLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"name"];
self.addressLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"address"];
self.phoneLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"phone"];
}
The issue is that you always accessing the array self.studentDetails even if it's empty. This will cause an exception.
First limit setting of the labels to a single method and check the array access will succeed before attempting it:
- (void)updateLabels
{
if (currentStudentIndex >= [self.studentDetails count])
return;
self.nameLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"name"];
self.addressLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"address"];
self.phoneLabel.text = [[self.studentDetails objectAtIndex:currentStudentIndex] valueForKey:#"phone"];
}
and use that method in the 3 places you currently set the labels. For example:
- (IBAction)clickPrevious:(id)sender {
currentStudentIndex--;
[self updateLabels];
}
- (IBAction)clickNext:(id)sender {
currentStudentIndex++;
[self updateLabels];
}
In the viewDidLoad method use this code:
...
sqlite3_finalize(selectStatement);
sqlite3_close(dataBase);
currentStudentIndex = 0;
[self updateLabels];
After that you're gonna want to work on enabling/disabling buttons depending on whether there is a next or previous student to view to make using the app more intuitive.
I am writing an app where I want to collect names and phone numbers from a list and add them into an array. How do I do this? I could retrieve first name and last name, but I don't get how to add a phone number in the below code as it is in a different for loop. It might look simple but I am stuck as I am new.
for (i = 0; i < [list count]; i++)
{
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty);
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
NSMutableArray *name = [NSMutableArray array];
if(firstName != nil)
[name addObject:firstName];
if(lastName != nil)
[name addObject:lastName];*/
[self displaynames:name];
ABMultiValueRef mobile=ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);
for (int k=0;k<ABMultiValueGetCount(mobile); k++)
{
NSString *mobileNo = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(mobile, k);
NSLog(#"mobile number: %#",mobileNo);
}
}
- (void)displaynames:(NSMutableArray*)names
{
for (NSMutableArray* name in names)
{
NSLog(#"MyResult:%# %#",[names objectAtIndex:0],[names objectAtIndex:1]);
}
}
So in the above code I am able to get the first name and last name from the list and add them into the array, similarly how do I get mobile phone number and add into the same array and get the result in the displayNames: function as it is another for loop. Can someone please edit the code and tell me what changes I have to make in the above code. Also in the result everything is being displayed twice why so?
NSMutableArray *contactList=[[NSMutableArray alloc] init];
for (int i=0; i<4; i++) {
NSMutableDictionary *contactInfo=[[NSMutableDictionary alloc] init];
for (int i = 0; i < [list count]; i++)
{
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty);
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
if (![firstName isEqualToString:#""]) {
[contactInfo setValue:firstName forKey:#"firstName"];
}
if (![lastName isEqualToString:#""]) {
[contactInfo setValue:lastName forKey:#"lastName"];
}
NSMutableArray *mobileNoArray=[[NSMutableArray alloc] initWithCapacity:ABMultiValueGetCount(mobile)];
ABMultiValueRef mobile=ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);
for (int k=0;k<ABMultiValueGetCount(mobile); k++)
{
NSString *mobileNo = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(mobile, k);
[mobileNoArray addObject:mobileNo];
}
if (mobileNoArray.count!=0) {
[contactInfo setObject:mobileNoArray forKey:#"mobileNo"]
}
}
[contactList addObject:contactInfo];
NSLog(#"contact info == %#",contactInfo);
}
NSLog(#"contact list array is %#",contactList);
So, instead using Array you have to use Dictionary to store FirstName, LastName and MobileNo with keyvalue Pair. If you have multiple user than use Array as upper layer, means add your user dictionary into array and when ever you want a user write the code:
for(NSDictionary *userDic in yourArray)
{
NSString *fName = [userDic valueForKey:#"FirstName"];
...
}
This is one of the way...
You can try to add the user info in a dictionary or create a model user object and store in the array. So all the information stays encapsulated in a single object.
self.users = [NSMutableArray array];
for (i = 0; i < [list count]; i++)
{
NSString *firstName = ...
NSString *lastName = ...
NSString *mobileNumber = ...
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
if(firstName)
userInfo[#"FirstName"] = firstName;
if(lastName)
userInfo[#"LastName"] = lastName;
if(mobileNumber)
userInfo[#"MobileNumber"] = mobileNumber;
[self.users addObject:userInfo];
}
You can enumerate using
[self.users enumerateObjectsUsingBlock:^(NSDictionary * userInfo, NSUInteger idx, BOOL *stop) {
NSString *firstName = userInfo[#"FirstName"];
NSString *mobileNumber = userInfo[#"MobileNumber"];
}];
Searching for a single user for a name
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"FirstName == %#",#"aUserName"];
NSDictionary *userInfo = [[self.users filteredArrayUsingPredicate:predicate]lastObject];
Try the following steps:
NSMutableArray *firstNames;
NSMutableArray *LastNames;
NSMutableArray *Mobile_numbers;
NSMutableArray *type_array;
NSMutableArray *firstandlast;
........
-(void)get_arr
{
ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *arrayOfPeople = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
NSUInteger index = 0;
firstNames = [[NSMutableArray alloc] init];
Mobile_numbers = [[NSMutableArray alloc] init];
type_array=[[NSMutableArray alloc]init ];
LastNames=[[NSMutableArray alloc]init ];
NSMutableArray *firstandlast;
#try
{
for(index = 0; index<=([arrayOfPeople count]-1); index++)
{
ABRecordRef currentPerson = (__bridge ABRecordRef)[arrayOfPeople objectAtIndex:index];
NSString *type;
ABMultiValueRef phones = (ABMultiValueRef)ABRecordCopyValue(currentPerson, kABPersonPhoneProperty);
for (int i=0; i < ABMultiValueGetCount(phones); i++)
{
//NSString *phone = (NSString *)ABMultiValueCopyValueAtIndex(phones, i);
////NSLog(#"%#", phone);
mobileLabel = (NSString*)ABMultiValueCopyLabelAtIndex(phones, i);
//NSLog(#"MOG:%#",mobileLabel);
if([mobileLabel isEqualToString:#"_$!<Mobile>!$_"]||[mobileLabel isEqualToString:#"_$!<Main>!$_"])
{
//NSLog(#"mobile:");
type=#"mobile";
}
else if ([mobileLabel isEqualToString:#"_$!<Work>!$_"])
{
//NSLog(#"Work:");
type=#"Work";
}
else if ([mobileLabel isEqualToString:#"_$!<Home>!$_"])
{
//NSLog(#"Home:");
type=#"Home";
}
else if ([mobileLabel isEqualToString:#"_$!<Other>!$_"] )
{
//NSLog(#"Other:");
type=#"Other";
}
mobile = (NSString*)ABMultiValueCopyValueAtIndex(phones, i);
//NSLog(#"GG:%#",mobile);
mobile = [mobile stringByReplacingOccurrencesOfString:#"-"
withString:#""];
mobile = [mobile stringByReplacingOccurrencesOfString:#"("
withString:#""];
mobile = [mobile stringByReplacingOccurrencesOfString:#")"
withString:#""];
mobile = [mobile stringByReplacingOccurrencesOfString:#" "
withString:#""];
[Mobile_numbers addObject:mobile];
[type_array addObject:type];
NSString *currentFirstName = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonFirstNameProperty);
////NSLog(#"NAME:%#",currentFirstName);
if ([currentFirstName length]!=0)
{
//NSLog(#"NAME:%#",currentFirstName);
[firstNames addObject:currentFirstName];
}
else
{
//NSLog(#"NAME:DUMMY");
currentFirstName=#"";
[firstNames addObject:currentFirstName];
}
NSString *currentLast = (__bridge_transfer NSString *)ABRecordCopyValue(currentPerson, kABPersonLastNameProperty);
////NSLog(#"NAME:%#",currentFirstName);
if ([currentLast length]!=0)
{
//NSLog(#"NAME:%#",currentLast);
[LastNames addObject:currentLast];
}
else
{
//NSLog(#"NAME:DUMMY");
currentLast=#"";
[LastNames addObject:currentLast];
}
NSString *temp_f_l=[NSString stringWithFormat:#"%# %#",currentFirstName,currentLast];
[firstandlast addObject:temp_f_l];
}
NSLog(#"MOB:%#",Mobile_numbers);
NSLog(#"TYPE:%#",type_array);
NSLog(#"FN:%#",firstNames);
NSLog(#"FN:%#",LastNames);
NSLog(#"FN&LN:%#",firstandlast);
}
}
#catch (NSException *exception)
{
//NSLog(#"CATCH");
}
}
In my Application. I am using this code to store Addressbook contents to Array. I hope it help for you.
I have created a code for Addressbook and contacts where display the contacts.It was working properly but suddenly getting Run time error .As I'm new to ios .I'm not able to find the error can any one in the Stack Overflow tell the error.
- (void)viewDidLoad
{
[super viewDidLoad];
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view.backgroundColor = [UIColor yellowColor];
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:#selector(gotohomepage:)]autorelease];
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
[[picker navigationBar] setBarStyle:UIBarStyleBlack];
picker.peoplePickerDelegate = self;
// Display only a person's phone, email, and birthdate
NSArray *displayedItems = [NSArray arrayWithObjects:[NSNumber numberWithInt:kABPersonPhoneProperty],nil];
picker.displayedProperties = displayedItems;
[self presentModalViewController:picker animated:YES];
[picker release];
}
- (IBAction)gotohomepage:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
ABAddressBookRef addressBook = ABAddressBookCreate();
int i;
NSString *strName = #"";
NSString* company = #"";
NSString *address = #"";
NSString *suburb = #"";
NSString *postalcode = #"";
NSString *state = #"";
NSString *country = #"";
NSString *mobile = #"";
NSString *phone = #"";
NSString *emailid = #"";
strName = (NSString *)ABRecordCopyCompositeName((ABRecordRef) person);
CFStringRef name = ABRecordCopyCompositeName((ABRecordRef) person);
company = (NSString *)ABRecordCopyValue((ABRecordRef) person, kABPersonOrganizationProperty);
NSArray* allPeople = (NSArray *)ABAddressBookCopyPeopleWithName(addressBook,name);
CFRelease(name);
for (i = 0; i < [allPeople count]; i++)
{
ABRecordRef record = [allPeople objectAtIndex:i];
ABMutableMultiValueRef multiValue = ABRecordCopyValue(record, kABPersonAddressProperty);
for(CFIndex i=0; i<ABMultiValueGetCount(multiValue); i++)
{
NSString* HomeLabel = (NSString*)ABMultiValueCopyLabelAtIndex(multiValue, i);
if([HomeLabel isEqualToString:#"_$!<Home>!$_"])
{
CFDictionaryRef dict = ABMultiValueCopyValueAtIndex(multiValue, i);
address = [NSString stringWithFormat:#"%#", CFDictionaryGetValue(dict, kABPersonAddressStreetKey)];
suburb = [NSString stringWithFormat:#"%#", CFDictionaryGetValue(dict, kABPersonAddressCityKey)];
postalcode = [NSString stringWithFormat:#"%#", CFDictionaryGetValue(dict, kABPersonAddressZIPKey)];
state = [NSString stringWithFormat:#"%#", CFDictionaryGetValue(dict, kABPersonAddressStateKey)];
country = [NSString stringWithFormat:#"%#", CFDictionaryGetValue(dict, kABPersonAddressCountryKey)];
CFRelease(dict);
}
CFRelease(HomeLabel);
}
CFRelease(multiValue);
}
CFRelease(allPeople);
ABMultiValueRef phones =(NSString*)ABRecordCopyValue(person, kABPersonPhoneProperty);
NSString* mobileLabel = nil;
for(CFIndex i = 0; i < ABMultiValueGetCount(phones); i++)
{
mobileLabel = (NSString*)ABMultiValueCopyLabelAtIndex(phones, i);
if([mobileLabel isEqualToString:(NSString *)kABPersonPhoneMobileLabel])
{
mobile = (NSString*)ABMultiValueCopyValueAtIndex(phones, i);
NSLog(#"phone %#",mobile);
}
else if ([mobileLabel isEqualToString:(NSString*)kABPersonPhoneIPhoneLabel])
{
phone = (NSString*)ABMultiValueCopyValueAtIndex(phones, i);
NSLog(#"phone %#",phone);
CFRelease(mobileLabel);
break ;
}
CFRelease(mobileLabel);
}
CFStringRef value, label;
ABMutableMultiValueRef multi = ABRecordCopyValue(person, kABPersonEmailProperty);
CFIndex count = ABMultiValueGetCount(multi);
if (count == 1)
{
value = ABMultiValueCopyValueAtIndex(multi, 0);
emailid = (NSString*) value;
NSLog(#"self.emailID %#",emailid);
CFRelease(value);
}
else
{
for (CFIndex i = 0; i < count; i++)
{
label = ABMultiValueCopyLabelAtIndex(multi, i);
value = ABMultiValueCopyValueAtIndex(multi, i);
// check for Work e-mail label
if (CFStringCompare(label, kABWorkLabel, 0) == 0)
{
emailid = (NSString*) value;
NSLog(#"self.emailID %#",emailid);
}
else if(CFStringCompare(label, kABHomeLabel, 0) == 0)
{
emailid = (NSString*) value;
NSLog(#"self.emailID %#",emailid);
}
CFRelease(label);
CFRelease(value);
}
}
CFRelease(multi);
CFRelease(phones);
CFRelease(addressBook);
[self dismissModalViewControllerAnimated:YES];
return NO;
}
On iOS6, apple introduce new privacy control, user can control the accessment of contact and calender by each app. So, in the code side, you need to add some way to request the permission. In iOS5 or before, we can always call
ABAddressBookRef addressBook = ABAddressBookCreate();
to get the addressbook without any problem, but in iOS6, if you don't have permission, this call will just return empty pointer. That why we need to change the method to get ABAddressBookRef.
This type of error generally appears when permission is not granted to access address book.In that case please add this piece of code
__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
accessGranted = granted;
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
dispatch_release(sema);
}
else { // we're on iOS 5 or older
accessGranted = YES;
}
if (accessGranted) {
// Do whatever you want here.
}
courtesy :- http://programmerjoe.blogspot.in/2012/10/ios6-permissions-contacts.html
If this doesn't solves your problem ping me back..
Error is that, because on IOS6 , Apple added some features that no one have permissions to get contents without owner's permission.
I am tring to get email address of ABRecordRef like this:
ABRecordRef ref = CFArrayGetValueAtIndex( allPeople, i );
NSString *email = [(NSString*) ABRecordCopyValue( ref, kABPersonEmailProperty ) autorelease];
NSLog(#"%#", email);
It returning this:
_$!<Home>!$_ (0x6840af0) - test#test.com (0x6840cc0)
What's this stuff around the email? and how can I get rid of it?Thanks.
kABPersonEmailProperty is of type kABMultiStringPropertyType. There is no single email address property, a person might have an email address for work, one for home, etc.
You can get an array of all email addresses by using ABMultiValueCopyArrayOfAllValues:
ABMultiValueRef emailMultiValue = ABRecordCopyValue(ref, kABPersonEmailProperty);
NSArray *emailAddresses = [(NSArray *)ABMultiValueCopyArrayOfAllValues(emailMultiValue) autorelease];
CFRelease(emailMultiValue);
To get the labels of the email addresses, use ABMultiValueCopyLabelAtIndex. "_$!<Home>!$" is a special constant that's defined as kABHomeLabel, there's also kABWorkLabel.
Basically more details for #omz answer. Here is the code I used that extracts home email and the name of the person:
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
for (CFIndex i = 0; i < ABMultiValueGetCount(emails); i++) {
NSString *label = (__bridge NSString *) ABMultiValueCopyLabelAtIndex(emails, i);
if ([label isEqualToString:(NSString *)kABHomeLabel]) {
NSString *email = (__bridge NSString *) ABMultiValueCopyValueAtIndex(emails, i);
_emailTextField.text = email;
}
}
CFRelease(emails);
NSString *first = (__bridge NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSString *last = (__bridge NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
if (first && first.length > 0 && last && last.length > 0) {
_nicknameTextField.text = [NSString stringWithFormat:#"%# %#", first, last];
} else if (first && first.length > 0) {
_nicknameTextField.text = first;
} else {
_nicknameTextField.text = last;
}
[self dismissModalViewControllerAnimated:YES];
return NO;
}
Try out this......
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
// Display only a person's phone, email, and birthdate
NSArray *displayedItems = [NSArray arrayWithObjects:
[NSNumber numberWithInt:kABPersonPhoneProperty],
[NSNumber numberWithInt:kABPersonEmailProperty],
[NSNumber numberWithInt:kABPersonBirthdayProperty], nil];
picker.displayedProperties = displayedItems;