As you may know we need to get rid of the older Addressbook framework and move everyone to newer Contacts framework. One of the feature we missed so far was querying history of contacts, so we can synchronise our database in the application with the system contacts database.
For the upcoming version 22.0 of MBS Xojo Plugins we add the CNChangeHistoryFetchRequestMBS class. This class allows you to build a request with various options like whether to include groups or whether to unify results. Here is some sample code:
Sub QueryHistory() // prepare request Dim request As New CNChangeHistoryFetchRequestMBS request.shouldUnifyResults = True request.includeGroupChanges = true request.startingToken = LastTimeToken // nil for all, old token to find new stuff // ask for more keys, so we have data to display dim keys() as CNKeyDescriptorMBS keys.Append CNContactMBS.CNContactOrganizationNameKey keys.Append CNContactMBS.CNContactGivenNameKey keys.Append CNContactMBS.CNContactFamilyNameKey keys.Append CNContactMBS.CNContactTypeKey request.setAdditionalContactKeyDescriptors keys dim error as NSErrorMBS dim result as CNFetchResultMBS = m.enumeratorForChangeHistoryFetchRequest(request, error) if error <> nil then MessageBox error.LocalizedDescription else ShowHistory result LastTimeToken = result.currentHistoryToken end if End Sub
If you like to show the results, you loop over the array and then check what subclass you got. All the changes have explicit subclasses and we got CNChangeHistoryRemoveSubgroupFromGroupEventMBS, CNChangeHistoryAddSubgroupToGroupEventMBS, CNChangeHistoryRemoveMemberFromGroupEventMBS, CNChangeHistoryAddMemberToGroupEventMBS, CNChangeHistoryDeleteGroupEventMBS, CNChangeHistoryUpdateGroupEventMBS, CNChangeHistoryAddGroupEventMBS, CNChangeHistoryDeleteContactEventMBS, CNChangeHistoryUpdateContactEventMBS, CNChangeHistoryAddContactEventMBS, CNChangeHistoryDropEverythingEventMBS and CNChangeHistoryFetchRequestMBS sub classes for CNFetchResultMBS class. In our example we check them like this:
Sub ShowHistory(result as CNFetchResultMBS) dim list as listbox = self.List dim items() as CNChangeHistoryEventMBS = result.ChangeHistoryEvents for each item as Variant in items if item isa CNChangeHistoryAddContactEventMBS then dim his as CNChangeHistoryAddContactEventMBS = item list.AddRow "Add contact "+his.contact.displayName elseif item isa CNChangeHistoryAddGroupEventMBS then dim his as CNChangeHistoryAddGroupEventMBS = item list.AddRow "Add group "+his.group.Name elseif item isa CNChangeHistoryAddSubgroupToGroupEventMBS then dim his as CNChangeHistoryAddSubgroupToGroupEventMBS = item list.AddRow "Add sub group "+his.subgroup.Name+" to "+his.group.Name elseif item isa CNChangeHistoryAddMemberToGroupEventMBS then dim his as CNChangeHistoryAddMemberToGroupEventMBS = item list.AddRow "Add member "+his.member.displayName+" to "+his.group.Name elseif item isa CNChangeHistoryDeleteContactEventMBS then dim his as CNChangeHistoryDeleteContactEventMBS = item list.AddRow "Delete contact "+his.contactIdentifier elseif item isa CNChangeHistoryDeleteGroupEventMBS then dim his as CNChangeHistoryDeleteGroupEventMBS = item list.AddRow "Delete group "+his.groupIdentifier elseif item isa CNChangeHistoryDropEverythingEventMBS then dim his as CNChangeHistoryDropEverythingEventMBS = item list.AddRow "Drop everything." elseif item isa CNChangeHistoryRemoveMemberFromGroupEventMBS then dim his as CNChangeHistoryRemoveMemberFromGroupEventMBS = item list.AddRow "Remove member "+his.member.displayName+" to "+his.group.Name elseif item isa CNChangeHistoryRemoveSubgroupFromGroupEventMBS then dim his as CNChangeHistoryRemoveSubgroupFromGroupEventMBS = item list.AddRow "Remove sub group "+his.subgroup.Name+" to "+his.group.Name elseif item isa CNChangeHistoryUpdateContactEventMBS then dim his as CNChangeHistoryUpdateContactEventMBS = item list.AddRow "Update contact "+his.contact.displayName elseif item isa CNChangeHistoryUpdateGroupEventMBS then dim his as CNChangeHistoryUpdateGroupEventMBS = item list.AddRow "Update group "+his.group.Name else Break end if next End Sub
Please try and see whether this works for you. Be aware that you can store a token for the last state you get via currentHistoryToken property in CNFetchResultMBS class to make another query later to find only newer changes. Our example app makes the initial query and then waits for DidChange event in CNContactStoreMBS subclass to make newer queries to update. Example and new classes are included in 22.0pr7 download.