Adding modification functionality in Contact sample

Previous: Sample on Contact-Sync in iOS

 Here, we will start coding where we left our previous article. In our previous article we only code for fetching device contacts at the first time when the app will start.

Now here we will add some other code which will be responsible for fetch contact as it is like our device contacts (means: if we will add, delete, or update the device contacts, at this time according to our app code it will not act like device contacts means no changes will be done in our application, because we are not written any code for any addition, deletion, or updation). 

Now, we will add those functionalists in our application which will make our
contact application more affective and after codding our contact app will also
take effect according to device contacts modification, for this follow the steps:

1.    In our AppDelegate.h file create a delegate which will be responsible for re-loading our table view after the changes in contacts, at the top of the @interface AppDelegate: interface declaration, write this code:

@class ViewController;

@protocol ContactDelegate <NSObject>

The required method contactChanged: will be responsible for reloading the table view and its declaration will be done in the ViewController, because our table view is declared in this class. 

2.       Now, add some methods: in AppDelegate.h file: 
-(NSMutableArray *)getUpdatedObjects:(NSMutableArray*)oldObj  andNewObj: (NSMutableArray*) newObj;

The above method is responsible for finding the updates in the device contacts like which person contact is added, deleted or updated. All these information will be found by the help of this method.

-(Person*)GetPersonFromID:(long)Id List:(NSMutableArray*)List;  

The above method will return modified person id from the new contacts array list, the returned object is used to update person contact modified information. 

Now, open the file and implement addressBookChanged: method, this method will be called from the didFinishLaunchingWithOptions: method, in this method we already added a line of code: ABAddressBookRegisterExternalChangeCallback(_addressBook, addressBookChanged, (__bridge void *)(self)); this like of code will execute whenever any changes will be done in the device contact a trigger will be fire and this method will be called addressBookChanged:, here is the complete implementation code:  

void addressBookChanged(ABAddressBookRef addressBook, CFDictionaryRef info, void *context)

NSLog(@"Recevied notification");
AppDelegate *obj=(__bridge AppDelegate*)context;
CFErrorRef error = nil;
ABAddressBookRef address = ABAddressBookCreateWithOptions(NULL,& error);
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 *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];
person.Id = contactId; person.firstName = firstName; person.middleName = middleName; person.lastName = lastName; person.modificationDate = modificationDate; person.contactNumber = cellN; person.contactType = cellT;
[newTableData addObject:person];
// Filtering ID from App Contacts
NSMutableArray *array1 = [obj.tableData mutableArrayValueForKey:@"Id"];
NSSet *Set1 = [[NSSet alloc] initWithArray:array1];
NSArray *app = [Set1 allObjects];
NSLog(@"FromApp Id: %@", app);
// Filtering ID from Phone Contacts
NSMutableArray *array2 = [newTableData mutableArrayValueForKey:@"Id"];
NSSet *Set2 = [[NSSet alloc] initWithArray:array2];
NSArray *phone = [Set2 allObjects];
NSLog(@"FromDiv Id: %@", phone);
// Collecting New Contacts and Deleted Contacts
NSMutableSet *newsetadded=[NSMutableSet setWithArray:array2];
NSMutableSet *oldsetdeleted=[NSMutableSet setWithArray:array1];
[newsetadded minusSet:[NSMutableSet setWithArray:array1]];
[oldsetdeleted minusSet:[NSMutableSet setWithArray:array2]];
NSLog(@"Pre: %tu",[obj.tableData count]);
NSLog(@"New: %tu\n",[newTableData count]);
// Adding new Contacts
if([newsetadded count]!=0) {
for(NSString *ID in newsetadded) {
[obj.tableData addObject:[obj GetPersonFromID:[ID longLongValue] List:newTableData]];
// Deleting removed Contacts
if([oldsetdeleted count]!=0) {
for(NSString *ID in oldsetdeleted) {
[obj.tableData removeObject:[obj GetPersonFromID:[ID longLongValue] List:obj.tableData]];
NSLog(@"Pre: %tu",[obj.tableData count]);
NSLog(@"New: %tu",[newTableData count]);
// Code for Updation in Phone Contacts
if([obj.tableData count]==[newTableData count]){
NSMutableArray *dateResult = [obj getUpdatedObjects:obj.tableData andNewObj:newTableData]; if(dateResult != nil){
for(int i=0; i<[dateResult count]; i++){ Person *oldPerson=[dateResult objectAtIndex:i];
Person *newPersonObj = [obj GetPersonFromID:[oldPerson.Id longValue] List:newTableData];
oldPerson.firstName = newPersonObj.firstName;
oldPerson.middleName = newPersonObj.middleName;
oldPerson.lastName = newPersonObj.lastName;
oldPerson.contactNumber = newPersonObj.contactNumber;
oldPerson.contactType = newPersonObj.contactType;
oldPerson.modificationDate = newPersonObj.modificationDate;
// Calling Custom delegate method of TableView
[obj.delegate contactChanged];

When the above method will execute, it will load new contacts(after the changes) and store them in new array list that will be used by the methods getUpdatedObjects: and GetPersonFromID:, after the executing both method we will do all type of modification (addition, deletion, or updation) in our contact application table view.

4. Now, the method GetPersonFromID: is used to get the person id which are added or deleted on the previous array list, it will be called from the addressBookChanged: method, here is the code:  

-(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 objectAtIndex:0]:nil;


5.  Now, the method getUpdatedObjects: is used to get the person object which are updated from the previous array list, it will be called from the addressBookChanged: method, here is the code: 

-(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 count]>0 ? list:nil;
Last updated:12/14/2017 6:26:01 AM


Leave Comment