Sunday, June 19, 2016

Detecting iOS device contact changes using Objective C

Whenever we need user's device contacts, We need to observe the external changes to the contacts in your app and update those contacts accordingly. Like in chat applications like WhatsApp. You add a new contact in your device, come back to WhatsApp, If your new contact is using WhatsApp, it will be visible in your WhatsApp contacts. That means, WhatsApp observes the changes in device contacts and updates accordingly. This has to be done in your apps also If we are accessing and playing with user's device contacts.

Let's see how can we detect these contact changes in an iOS device using Objective C for both ABAddressBook and the new CNContactStore.


ABAddressBook is having a external contact changes callback which we need to register for for getting contact changes.

    ABAddressBookRef ntificationaddressbook   
                              = ABAddressBookCreateWithOptions(NULLnil);

                   DeviceContactsExtenalChangeCallback, (__bridge void *)(self));

     void DeviceContactsExtenalChangeCallback  (ABAddressBookRef ntificationaddressbook,CFDictionaryRef info,void *context)

        NSLog(@"Change in device contacts!");
        CFArrayRef peopleRefs ABAddressBookCopyArrayOfAllPeopleInSource
                          (ntificationaddressbook, kABSourceTypeLocal);
        CFIndex count = CFArrayGetCount(peopleRefs);
        for (CFIndex i=0; i < count; i++) {
            ABRecordRef aSource = CFArrayGetValueAtIndex(peopleRefs,i);
            NSString *first_name =nil;
            NSString *mid_name = nil ;
            NSString *last_name =nil ;
            first_name= (__bridge NSString *)
                     (ABRecordCopyValue(aSource, kABPersonFirstNameProperty));

            mid_name= (__bridge NSString *)
                     (ABRecordCopyValue(aSource, kABPersonMiddleNameProperty));

            last_name= (__bridge NSString *)
                     (ABRecordCopyValue(aSource, kABPersonLastNameProperty));
            NSDate* contactModifiedDate = (__bridge  NSDate *)
                      (ABRecordCopyValue(aSource, kABPersonModificationDateProperty));
            NSLog(@"name : %@ , datemod : %@",first_name,contactModifiedDate);

      As per above code, when you register for external change callback method 'DeviceContactsExtenalChangeCallback',
      Whenever there is a contact change, this callback method will get called.

         To Register :->

           (ntificationaddressbook, DeviceContactsExtenalChangeCallback,
                                                                             (__bridge void *)(self));

         To Unregister :->

                                                                             (__bridge void *)(self));

        Where to register and where to unregister this callback depends on our app requirement.

        Based on the kABPersonModificationDateProperty of a contact, We can know whether it is a latest change or not.    

               Change in device contacts!

               name : Daniel , datemod : 2016-05-09 17:11:39 +0000
               name : Anna1 , datemod : 2016-06-19 08:39:18 +0000
               name : Hank , datemod : 2016-05-09 17:11:39 +0000
               name : Karunakar , datemod : 2016-06-19 08:37:27 +0000

          Based on the above log, Contacts Anna and karunakar have been updated/added recently.


          Using latest CNContactStore, It is as simple as observing for CNContactStoreDidChangeNotification,

              [[NSNotificationCenter defaultCenteraddObserver:self 
                       name:CNContactStoreDidChangeNotification object:nil];


                   NSLog(@"Change in contacts!");    

          Hope this post is useful. Feel free to comment incase of any queries.