blog

Home / DeveloperSection / Blogs / Access iPhone/iPad contact list using Address Book and display contact list in UITableView in iOS

Access iPhone/iPad contact list using Address Book and display contact list in UITableView in iOS

Sunil Singh1883 13-Jan-2017

Step-1  Create a new project.

Step- 2 Add AddressBook.framework to the project.

Step-3 Import “AddressBook/AddressBook.h” in AppDelegate.h following is the appdelegate.h and appdelegate.mm

Step- 4  Add ViewController in storyboard and add a UITableView on it . Below is the UI ViewController code and other supporting classes.


//
// AppDelegate.h
// ContactsDemo
//
// Copyright (c) 2017 mindstick. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <AddressBook/AddressBook.h>
#import "Person.h"
@class ViewController;
@interface AppDelegate : UIResponder <UIApplicationDelegate>{
}
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) ViewController *viewController;
@property ABAddressBookRef addressBook;

@property(nonatomic, strong) NSMutableArray *tableData;
-(NSMutableArray *)getUpdatedObjects:(NSMutableArray*)oldObj andNewObj:(NSMutableArray*)newObj;
-(Person*)GetPersonFromID:(long)Id List:(NSMutableArray*)List;
@end
//
// AppDelegate.m
// ContactsDemo
//
// Copyright (c) 2017 mindstick. All rights reserved.
//
#import "AppDelegate.h"
#import "ViewController.h"

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSString *phNo = @"+917505311263";
NSURL *phoneUrl = [NSURL URLWithString:[NSString stringWithFormat:@"telprompt:%@",phNo]];
if ([[UIApplication sharedApplication] canOpenURL:phoneUrl]) {
[[UIApplication sharedApplication] openURL:phoneUrl];
} else
{
UIAlertView *calert = [[UIAlertView alloc]initWithTitle:@"Alert" message:@"Call facility is not available!!!" delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];
[calert show];
}
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
__block BOOL accessGranted = NO;
// [self getContactsFromAddressBook];
_addressBook = ABAddressBookCreate();
if (&ABAddressBookRequestAccessWithCompletion != NULL) { // We are on iOS 6
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(_addressBook, ^(bool granted, CFErrorRef error) {
accessGranted = granted;
dispatch_semaphore_signal(semaphore);
});
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
ABAddressBookRegisterExternalChangeCallback(_addressBook, addressBookChanged, (__bridge void *)(self));
// });
// Override point for customization after application launch.
self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
self.tableData = [[NSMutableArray alloc] init];
[self getContactsFromAddressBook];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
- (void)getContactsFromAddressBook
{
if(self.tableData.count<=0){
CFErrorRef error = nil;
ABAddressBookRef phoneContacts = ABAddressBookCreateWithOptions(NULL, &error);
if (phoneContacts != nil) {
//NSLog(@"Contacts are available.");
NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(phoneContacts);
// NSLog(@"%@",allContacts);
NSUInteger i = 0;
for(i = 0; i < [allContacts count]; i++)
{
ABRecordRef contactPerson = (__bridge ABRecordRef)allContacts[i];
NSNumber *contactId = [NSNumber numberWithInt:ABRecordGetRecordID(contactPerson)];
NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty);
NSString *middleName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonMiddleNameProperty);
NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
NSDate *modificationDate = (__bridge_transfer NSDate *)ABRecordCopyValue(contactPerson, kABPersonModificationDateProperty);
// Getting no of person contact numbers
ABMultiValueRef numbersArr = ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);
NSUInteger j = 0;
for(j = 0; j < ABMultiValueGetCount(numbersArr); j++)
{
NSString *cellN = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(numbersArr, j);
NSString *cellT =(__bridge NSString*)ABAddressBookCopyLocalizedLabel( ABMultiValueCopyLabelAtIndex(numbersArr, j));
Person *person = [Person new];
// Getting Id,first,middle,last name
person.Id = contactId; //NSLog(@"ID: %@",contactId);
person.firstName = firstName; //NSLog(@"%@",person.firstName);
person.middleName = middleName; //NSLog(@"%@",person.middleName);
person.lastName = lastName; //NSLog(@"%@",person.lastName);
person.modificationDate = modificationDate; // NSLog(@"%@",person.modificationDate);
person.contactNumber = cellN;
person.contactType = cellT;
[self.tableData addObject:person];
}
}
CFRelease(phoneContacts);
} else {
NSLog(@"Error reading Address Book");
}
}
}
//
void addressBookChanged(ABAddressBookRef addressBook, CFDictionaryRef info, void *context) {
NSLog(@"Recevied notification");
AppDelegate *obj=(__bridge AppDelegate*)context;
ABAddressBookRef address = ABAddressBookCreate();
NSMutableArray *newTableData = [[NSMutableArray alloc] init];
NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(address);
NSUInteger i = 0;
for(i = 0; i < [allContacts count]; i++)
{
ABRecordRef contactPerson = (__bridge ABRecordRef)allContacts[i];
NSNumber *contacts = [NSNumber numberWithInt:ABRecordGetRecordID(contactPerson)];
// NSLog(@"contactId=%@",contactId);
NSString *first = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty);
// NSLog(@"firstName=%@",firstName);
NSString *middle = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonMiddleNameProperty);
NSString *last = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
NSDate *date = (__bridge_transfer NSDate *)ABRecordCopyValue(contactPerson, kABPersonModificationDateProperty);
// NSLog(@"modificationDate=%@",modificationDate);
ABMultiValueRef numbersArr1 = ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);
NSUInteger k = 0;
for(k = 0; k < ABMultiValueGetCount(numbersArr1); k++)
{
NSString *cellN = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(numbersArr1, k);
NSString *cellT =(__bridge NSString*)ABAddressBookCopyLocalizedLabel( ABMultiValueCopyLabelAtIndex(numbersArr1, k));
Person *personObj = [Person new];
// Getting Id,first,middle,last name
personObj.Id = contacts;
personObj.firstName = first;
personObj.middleName = middle;
personObj.lastName = last;
personObj.modificationDate = date;
personObj.contactNumber = cellN;
personObj.contactType = cellT;
[newTableData addObject:personObj];
}
}
NSLog(@"Pre: %tu",[obj.tableData count]);
NSLog(@"New: %tu",[newTableData count]);
NSMutableArray *array1 = [obj.tableData mutableArrayValueForKey:@"Id"];
NSSet *Set1 = [[NSSet alloc] initWithArray:array1];
NSArray *app = [Set1 allObjects];
NSLog(@"FromApp Id: %@", app);
NSMutableArray *array2 = [newTableData mutableArrayValueForKey:@"Id"];
NSSet *Set2 = [[NSSet alloc] initWithArray:array2];
NSArray *phone = [Set2 allObjects];
NSLog(@"FromDiv Id: %@", phone);
NSMutableSet *newsetadded=[NSMutableSet setWithArray:array2];
NSMutableSet *oldsetdeleted=[NSMutableSet setWithArray:array1];
[newsetadded minusSet:[NSMutableSet setWithArray:array1]];
[oldsetdeleted minusSet:[NSMutableSet setWithArray:array2]];
if([newsetadded count]!=0){
for(int i=0; i<[newsetadded count]; i++){
// Person *newPerson = [obj GetPersonFromID: List:newTableData];
}
}
NSMutableArray *dateResult = [obj getUpdatedObjects:obj.tableData andNewObj:newTableData];
for(int i=0; i<[dateResult count]; i++){
Person *oldPerson=[dateResult objectAtIndex:i];
Person *newPersonObj = [obj GetPersonFromID:[oldPerson.Id longValue] List:newTableData];
NSLog(@"%@ : %@",newPersonObj.firstName,oldPerson.firstName);
oldPerson.firstName = newPersonObj.firstName;
}
}
-(Person*)GetPersonFromID:(long)Id List:(NSMutableArray*)List{
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"Id=%ld",Id];
NSMutableArray *FilteredList=[[List filteredArrayUsingPredicate:predicate] mutableCopy];
predicate=nil;
return FilteredList.count>0?FilteredList.firstObject:nil;
}
-(NSMutableArray *)getUpdatedObjects:(NSMutableArray*)oldObj andNewObj:(NSMutableArray*)newObj
{
NSMutableArray *list=[NSMutableArray new];
for(int i=0; i<[oldObj count]; i++){
Person *p1 = [oldObj objectAtIndex:i];
Person *p2 = [newObj objectAtIndex:i];
if([p1.modificationDate compare:p2.modificationDate] != NSOrderedSame){
NSLog(@"ModifiedId: %tu and Date: %@",p1.Id,p1.modificationDate);
[list addObject:p1];
}
}
return list;
}

@end
//
// ViewController.h
// ContactsDemo
//
// Copyright (c) 2017 mindstick. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
@interface ViewController : UIViewController<UITableViewDataSource, UITableViewDelegate>
@property(nonatomic,strong) AppDelegate *obj;
@end
//
// ViewController.m
// ContactsDemo
//
// Copyright (c) 2017 mindstick. All rights reserved.
//

#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.title = @"Contacts";
_obj=(AppDelegate*)[UIApplication sharedApplication].delegate;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_obj.tableData count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
}
Person *person = [_obj.tableData objectAtIndex:indexPath.row];
cell.textLabel.text = [[NSString alloc] initWithFormat:@"%@ ",person.firstName];
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:@"%@: %@",person.contactType,person.contactNumber];
return cell;
}

@end

//
// Person.h
// ContactsDemo
//
// Copyright (c) 2017 mindstick. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic, strong) NSNumber *Id;
@property (nonatomic, strong) NSString *firstName;
@property (nonatomic, strong) NSString *middleName;
@property (nonatomic, strong) NSString *lastName;
@property (nonatomic, strong) NSString *contactNumber;
@property (nonatomic, strong) NSString *contactType;
@property (nonatomic, strong) NSDate *modificationDate;
@end
//
// Person.m
// ContactsDemo
//
// Copyright (c) 2017 mindstick. All rights reserved.
//
#import "Person.h"
@implementation Person
@synthesize Id;
@synthesize firstName;
@synthesize middleName;
@synthesize lastName;
@synthesize contactNumber;
@synthesize contactType;
@synthesize modificationDate;
@end


Following is the screen shot of contact Sample-

Access iPhone/iPad contact list using Address Book and display contact list in UITableView in iOS


Updated 17-Mar-2018

Leave Comment

Comments

Liked By