I need to make a UITableView which fetches address book contents in it and also a UISearchBar which searches the address book contents.
I need an implementation like this project
http://www.appcoda.com/search-bar-tutorial-ios7/
But the problem is here the data is static and I want to load address book's data in it.
I have created ContactData NSObject Class. In following method, I am creating its object for each contact. At the end, you will get NSMutableArray named contactArr.
-(void)loadContacts{
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
//NSLog(#"%#", addressBook);
});
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
CFErrorRef *error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);
for(int i = 0; i < numberOfPeople; i++) {
ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );
NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
ContactData *dataObj = [[ContactData alloc]init];
NSString *Name = #" ";
if ([firstName length]>0) {
if ([lastName length]>0) {
Name = [NSString stringWithFormat:#"%# %#",firstName,lastName];
}
else{
Name = firstName;
}
}
else{
Name = #" ";
}
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
[[UIDevice currentDevice] name];
//NSLog(#"\n%#\n", [[UIDevice currentDevice] name]);
NSString *phoneNumber = #" ";
for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
}
ABMultiValueRef Emails = ABRecordCopyValue(person, kABPersonEmailProperty);
[[UIDevice currentDevice] name];
NSString *Email; //= #" ";
for (CFIndex i = 0; i < ABMultiValueGetCount(Emails); i++) {
Email = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(Emails, i);
}
ABMultiValueRef Addresses = ABRecordCopyValue(person, kABPersonAddressProperty);
NSString *address = #" ";
NSMutableDictionary* addressDict = [[NSMutableDictionary alloc]init];
for (CFIndex i = 0; i < ABMultiValueGetCount(Addresses); i++) {
addressDict = (__bridge_transfer NSMutableDictionary *) ABMultiValueCopyValueAtIndex(Addresses, i);
//NSLog(#"address = %#", addressDict);
NSString * street = [addressDict objectForKey:#"Street"];
NSString * city = [addressDict objectForKey:#"City"];
NSString * state = [addressDict objectForKey:#"State"];
NSString *country = [addressDict objectForKey:#"Country"];
if (country.length>0 || state.length>0 || city.length>0 || street.length>0) {
if (country.length>0 && state.length>0) {
address = [NSString stringWithFormat:#"%#, %#", state,country];
}
else if(country.length>0 && city.length>0){
address = [NSString stringWithFormat:#"%#, %#", city,country];
}
else if (state.length>0 && street.length>0){
address = [NSString stringWithFormat:#"%#, %#", street,country];
}
else if (state.length>0 && city.length>0){
address = [NSString stringWithFormat:#"%#, %#", city,state];
}
else if (state.length>0 && street.length>0){
address = [NSString stringWithFormat:#"%#, %#", street,state];
}
else if (city.length>0 && street.length>0){
address = [NSString stringWithFormat:#"%#, %#", street,city];
}
else if (country.length>0){
address = country;
}
else if (state.length>0){
address = state;
}
else if (city.length>0){
address = city;
}
}
else{
address = #" ";
}
}
//NSLog(#"address = %#", address);
NSData *imgData = (__bridge_transfer NSData *) ABPersonCopyImageDataWithFormat(person, kABPersonImageFormatThumbnail);
dataObj.name = Name;
dataObj.email = Email;
dataObj.phone = phoneNumber;
dataObj.imageData = imgData;
dataObj.address = address;
[contactArr addObject:dataObj];
}
NSLog(#"contacts loaded");
//NSLog(#"count = %lu", (unsigned long)contactArr.count);
}
else {
//Go to settings and allow access to use contacts[GlobalFunction removeWaitView];
}
}
First make sure you have the correct frameworks imported:
#import <AddressBook/AddressBook.h>
Fetch the contacts of AddressBook like this:
ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );
for ( int i = 0; i < nPeople; i++ )
{
ABRecordRef ref = CFArrayGetValueAtIndex( allPeople, i );
//further code
}
Then populate the UITableView as usual (as per the example you already provided).
Thankfully this framework is being deprecated. The new Contacts API in iOS 9 is gorgeous.
Related
I am new in IOS Programming. In my simple app I am storing first name,last name and phone number in NSMutableArray.I have a UITextfield where I get the phone number.I wanna search first name and last name according to mobile number.I am storing firstname, lastname and phone number in different Mutable arrays so how to search firstname and lastname in stored array.
This is my code
ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, NULL);
_firstname = [[NSMutableArray alloc]init];
_lastname = [[NSMutableArray alloc]init];
_number = [[NSMutableArray alloc]init];
_fullname = [[NSMutableArray alloc]init];
_arrContacts = [[NSMutableArray alloc]init];
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
ABAddressBookRequestAccessWithCompletion(addressBookRef, ^(bool granted, CFErrorRef error) {
ABAddressBookRef addressBook = ABAddressBookCreate( );
});
}
else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
CFErrorRef *error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);
for(int i = 0; i < numberOfPeople; i++) {
ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );
NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
if (firstName != nil) {
[_firstname addObject:firstName];
}
else{
[_firstname addObject:#"Not Found"];
}
if (lastName != nil) {
[_lastname addObject:lastName];
}
else{
[_lastname addObject:#"Not Found"];
}
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
[[UIDevice currentDevice] name];
NSArray *numbers = (__bridge NSArray *)(ABMultiValueCopyValueAtIndex(phoneNumbers, 0));
if (numbers != nil) {
[_arrContacts addObject:numbers];
NSLog(#"Numbers:%#",_arrContacts);
}
for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
_addressBookNum = [_addressBookNum stringByAppendingFormat: #":%#",phoneNumber];
}
}
// NSLog(#"AllNumber:%#",_addressBookNum);
}
else {
// Send an alert telling user to change privacy setting in settings app
}
CFRelease(addressBookRef);
NSLog(#"This is Name: %#",_firstname);
NSLog(#"This is LastName: %#",_lastname);
NSLog(#"Number: %#",_arrContacts);
}
Please suggest some idea to do this
Instead of saving name last name and number in different array store it in single array with dictionary. Suppose NSMutabelArray *details
create dictionary having three values name lastname and number, and add this dictoianry into array,
so it will be easy for you to further use
i m using following code for Backup Full Address Book.
CFErrorRef error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);
CFArrayRef peopleForBackup = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFDataRef vcards = (CFDataRef)ABPersonCreateVCardRepresentationWithPeople(peopleForBackup);
NSString *vcardString = [[NSString alloc] initWithData:(NSData *)CFBridgingRelease(vcards) encoding:NSUTF8StringEncoding];
in Above code i can not get Notes from Contacts.
Please help me, how can i take a full address book as a Backup..?
get Complete Address Book ,
-(void)getAddressbookContacts
{
//Get Contacts From PhoneBook Contacts
NSString *fullName;
UIImage *img;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, nil);
NSInteger numberOfPeople = ABAddressBookGetPersonCount(addressBook);
NSArray *allPeople = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
for (NSInteger i = 0; i < numberOfPeople; i++) {
ABRecordRef person = (__bridge ABRecordRef)allPeople[i];
// get phone numbers
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSString* mobile=#"";
NSString* mobileLabel;
CFIndex numberOfPhoneNumbers = ABMultiValueGetCount(phoneNumbers);
for (CFIndex i = 0; i < numberOfPhoneNumbers; i++)
{
mobileLabel = (__bridge NSString*)ABMultiValueCopyLabelAtIndex(phoneNumbers, i);
// NSLog(#"mobileLabel=%#",mobileLabel);
//Only add numbers who have saved in Mobile or IPhone (eg.Home,Work,..)
if([mobileLabel isEqualToString:(__bridge NSString *)kABPersonPhoneMobileLabel] || [mobileLabel isEqualToString:(__bridge NSString *)kABPersonPhoneIPhoneLabel])
{
NSString *phoneNumber = CFBridgingRelease(ABMultiValueCopyValueAtIndex(phoneNumbers, i));
phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:#"-" withString:#""];
phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:#" " withString:#""];
phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:#"(" withString:#""];
phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:#")" withString:#""];
phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:#" " withString:#""];
// phoneNumber = [phoneNumber stringByReplacingOccurrencesOfString:#"+" withString:#""];
// NSLog(#"phoneNumber=%#",phoneNumber);
// contact number should be mobile number or iphone
mobile = (__bridge NSString*)ABMultiValueCopyValueAtIndex(phoneNumbers, i);
NSString *firstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
// ABMultiValueRef emailMultiValue = ABRecordCopyValue(person, kABPersonEmailProperty);
//Fetch Email Address of Contact
// NSArray *emailAddresses = (__bridge NSArray *)ABMultiValueCopyArrayOfAllValues(emailMultiValue);
//NSLog(#"email is %#",emailAddresses);
//Fetch Image of Contact
NSData *imgData = (__bridge NSData *)ABPersonCopyImageData(person);
if(lastName == nil)
{
fullName = firstName;
}
else
{
fullName = [firstName stringByAppendingString:#" "];
fullName = [fullName stringByAppendingString:lastName];
}
if(imgData == nil)
{
//NSLog(#"no image found");
img = [UIImage imageNamed:#"contact"];
}
else
{
img = [UIImage imageWithData:imgData];
}
NSMutableDictionary *dictContactDetails = [[NSMutableDictionary alloc]init];
[dictContactDetails setValue:fullName forKey:#"full_name"];
[dictContactDetails setValue:img forKey:#"profile_image"];
[dictContactDetails setValue:mobile forKey:#"mobile_number"];
[dictContactDetails setValue:phoneNumber forKey:#"number"];
//Add Fullname,Image & number into Array & Display it into Table
[arrayOfInviteContacts addObject:dictContactDetails];
}
}
CFRelease(phoneNumbers);
}
NSLog(#"arrayOfInviteContacts=%lu, %#",(unsigned long)arrayOfInviteContacts.count,arrayOfInviteContacts);
[tblInviteFriends reloadData];
}
How can i Edit Specific Address book First Name and Last Name Programatically .Could any one Guide me to found this.
Am getting Contact Recode like below.
Email = (
"John-Appleseed#mac.com"
);
First = John;
Last = Appleseed;
numbers = (
"888-555-5512",
"888-555-1212"
);
}
How can i edit the First and last Values.
I used Below code to Fetch contact details from Device
CFErrorRef * error = NULL;
addressBook = ABAddressBookCreateWithOptions(NULL, error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error)
{
if (granted)
{
dispatch_async(dispatch_get_main_queue(), ^{
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);
for(int i = 0; i < numberOfPeople; i++){
ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );
NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
NSString *name=[NSString stringWithFormat:#"%# %#",firstName,lastName];
NSString *Birthday=(__bridge NSString *)(ABRecordCopyValue(person, kABPersonBirthdayProperty));
NSLog(#"Name:%# %# %#", firstName, lastName,Birthday);
//For Email ids
NSMutableArray *Emails = [NSMutableArray array];
ABMutableMultiValueRef eMail = (__bridge ABMutableMultiValueRef)((__bridge NSString *) ABRecordCopyValue(person, kABPersonEmailProperty));
for (CFIndex i = 0; i < ABMultiValueGetCount(eMail); i++) {
NSString *emails = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(eMail, i);
[Emails addObject:emails];
}
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
NSMutableArray *numbers = [NSMutableArray array];
for (CFIndex i = 0; i < ABMultiValueGetCount(phoneNumbers); i++) {
NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
[numbers addObject:phoneNumber];
}
NSMutableDictionary *contact = [NSMutableDictionary dictionary];
[contact setObject:firstName forKey:#"First"];
[contact setObject:lastName forKey:#"Last"];
[contact setObject:numbers forKey:#"numbers"];
[contact setObject:Emails forKey:#"Email"];
NSLog(#" contacts are %#",contact);
[all_contacts addObject:contact];
NSLog(#"all contacts are %#",all_contacts);
[self.tbl_contacts reloadData];
}
});
}
});
First pick the required contact:
- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker
shouldContinueAfterSelectingPerson:(ABRecordRef)person
{
[self peoplePickerNavigationController:peoplePicker didSelectPerson:person];
return NO;
}
Refer this: for setting and getting first name and last name
ABRecordRef aRecord = ABPersonCreate();
CFErrorRef anError = NULL;
bool didSet;
didSet = ABRecordSetValue(aRecord, kABPersonFirstNameProperty, CFSTR("Katie"), &anError);
if (!didSet) {/* Handle error here. */}
didSet = ABRecordSetValue(aRecord, kABPersonLastNameProperty, CFSTR("Bell"), &anError);
if (!didSet) {/* Handle error here. */}
CFStringRef firstName, lastName;
firstName = ABRecordCopyValue(aRecord, kABPersonFirstNameProperty);
lastName = ABRecordCopyValue(aRecord, kABPersonLastNameProperty);
/* ... Do something with firstName and lastName. ... */
CFRelease(aRecord);
CFRelease(firstName);
CFRelease(lastName);
I have used following code block in order to retrieve the contacts. The problem is, non of the values are assigned it seems in "contacts" array as expected at the end. I'm very new to threading in iOS. If someone could help me in this, thanks a bunch.
CFErrorRef * error = NULL;
ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, error);
ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error)
{
if (granted)
{
dispatch_async(dispatch_get_main_queue(), ^{
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex numberOfPeople = ABAddressBookGetPersonCount(addressBook);
for(int i = 0; i < numberOfPeople; i++){
ABRecordRef person = CFArrayGetValueAtIndex( allPeople, i );
NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
NSString *name = [NSString stringWithFormat:#"%# %#", firstName, lastName];
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);
NSUInteger j = 0;
if (emails) {
for (j = 0; j < ABMultiValueGetCount(emails); j++) {
NSString *email = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(emails, j);
if (j == 0) {
[emailConatcts setValue:email forKey:name];
[contacts addObject:emailConatcts];
}
}
}
ABMultiValueRef phoneNumbers = ABRecordCopyValue(person, kABPersonPhoneProperty);
if (phoneNumbers) {
CFIndex numberOfPhoneNumbers = ABMultiValueGetCount(phoneNumbers);
for (CFIndex i = 0; i < numberOfPhoneNumbers; i++) {
CFStringRef label = ABMultiValueCopyLabelAtIndex(phoneNumbers, i);
if (label) {
if (CFEqual(label, kABPersonPhoneMobileLabel)) {
NSString *phoneNumber = (__bridge_transfer NSString *) ABMultiValueCopyValueAtIndex(phoneNumbers, i);
[mobileContacts setValue:phoneNumber forKey:name];
[contacts addObject:emailConatcts];
}
}
}
}
}
});
}
});
NSLog(#"contacts: %#", contacts);
You are asking for the contacts before you have them apparently.
If you move this line
NSLog(#"contacts: %#", contacts);
before this
});
}
});
You should see the data.
The reason is, when you use dispach, and completion blocks, you are telling the system to run that code (usually in a different thread) after a certain operation has finished. So when you were printing the contacts, that block code had not run yet.
So whatever you need to do with the contacts, call it inside that block :)
I am doing an iPhone app in Xcode that needs phone book accessing. I need all phone numbers from address book and that should be stored in an NSArray.
//Also you need to include AddressBook.framework
#import <AddressBook/AddressBook.h>
#import <AddressBook/ABAddressBook.h>
#import <AddressBook/ABPerson.h>
[contactList removeAllObjects];
// open the default address book.
ABAddressBookRef m_addressbook = ABAddressBookCreate();
if (!m_addressbook) {
NSLog(#"opening address book");
}
// can be cast to NSArray, toll-free
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(m_addressbook);
CFIndex nPeople = ABAddressBookGetPersonCount(m_addressbook);
// CFStrings can be cast to NSString!
for (int i=0;i < nPeople;i++) {
MContact *contact = [[MContact alloc] init];
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople,i);
CFStringRef firstName, lastName;
firstName = ABRecordCopyValue(ref, kABPersonFirstNameProperty);
lastName = ABRecordCopyValue(ref, kABPersonLastNameProperty);
contact.name = [NSString stringWithFormat:#"%# %#", firstName, lastName];
ABMutableMultiValueRef eMail = ABRecordCopyValue(ref, kABPersonEmailProperty);
if(ABMultiValueGetCount(eMail) > 0) {
contact.email = (NSString *)ABMultiValueCopyValueAtIndex(eMail, 0);
[contactList addObject:contact];
}
CFRelease(ref);
CFRelease(firstName);
CFRelease(lastName);
}
Try this,
NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
ABMultiValueRef multiPhones = ABRecordCopyValue(person,kABPersonPhoneProperty);
for(CFIndex i=0;i<ABMultiValueGetCount(multiPhones);++i) {
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(multiPhones, i);
NSString *phoneNumber = (NSString *) phoneNumberRef;
[phoneNumbers addObject:phoneNumber];
}
This code for Xcode 4.5.1>=0, if if you have below version then no need write if condition. just assign ABAddressBookCreate() to addressbook.
__block BOOL accessGranted = NO;
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"6.0")) {
NSLog(#"Device version is greater than 6.0");
addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
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);
}
}
else{
addressBook = ABAddressBookCreate();
accessGranted = YES;
}
if (accessGranted) {
NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];
CFArrayRef people = ABAddressBookCopyArrayOfAllPeople(addressBook);
for (CFIndex i = 0; i < CFArrayGetCount(people); i++) {
ABRecordRef person = CFArrayGetValueAtIndex(people, i);
NSString *name = (__bridge NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
ABMultiValueRef multiPhones = ABRecordCopyValue(person,kABPersonPhoneProperty);
NSMutableArray *individualPhoneNumbers = [[NSMutableArray alloc] init];
if (ABMultiValueGetCount(multiPhones) >0) {
for(CFIndex i=0;i<ABMultiValueGetCount(multiPhones);++i) {
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(multiPhones, i);
NSString *phoneNumber = (__bridge NSString *) phoneNumberRef;
[individualPhoneNumbers addObject:phoneNumber];
}
[phoneNumbers addObject:individualPhoneNumbers];
}
}