Contacts history for Xojo

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
		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 "
		elseif item isa CNChangeHistoryAddGroupEventMBS then
			dim his as CNChangeHistoryAddGroupEventMBS = item
			list.AddRow "Add group "
		elseif item isa CNChangeHistoryAddSubgroupToGroupEventMBS then
			dim his as CNChangeHistoryAddSubgroupToGroupEventMBS = item
			list.AddRow "Add sub group "+his.subgroup.Name+" to "
		elseif item isa CNChangeHistoryAddMemberToGroupEventMBS then
			dim his as CNChangeHistoryAddMemberToGroupEventMBS = item
			list.AddRow "Add member "+his.member.displayName+" to "
		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 "
		elseif item isa CNChangeHistoryRemoveSubgroupFromGroupEventMBS then
			dim his as CNChangeHistoryRemoveSubgroupFromGroupEventMBS = item
			list.AddRow "Remove sub group "+his.subgroup.Name+" to "
		elseif item isa CNChangeHistoryUpdateContactEventMBS then
			dim his as CNChangeHistoryUpdateContactEventMBS = item
			list.AddRow "Update contact "
		elseif item isa CNChangeHistoryUpdateGroupEventMBS then
			dim his as CNChangeHistoryUpdateGroupEventMBS = item
			list.AddRow "Update group "
		end if
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.

Forum for Xojo Programming Language and IDE. Copyright © 2021 Xojo, Inc.