I need to prevent display of contact groups within our app however it is intrusive to the user to simply remove Groups from the AddressBook. So I'm attempting to remove them before display contacts, and then add them back when finished so that the AddressBook is left unchanged and the iOS Contacts app displays the groups as they were. I created two Arrays for storing the info:
NSArray *aGroups;
NSMutableArray *aGroupMembers;
I remove the groups, store them, and display the picker in viewWillAppear:
// Remove group records for the life of this view.
CFErrorRef error;
ABAddressBookRef abRef = ABAddressBookCreate();
NSArray *groups = (NSArray *)ABAddressBookCopyArrayOfAllGroups(abRef);
if (groups.count > 0) {
// we will remove the groups so save for restoration
self.aGroups = [[NSArray alloc] initWithArray:groups];
aGroupMembers = [[NSMutableArray alloc] initWithCapacity:groups.count];
for (int i = 0; i < groups.count; i++) {
NSArray *members = (NSArray *)ABGroupCopyArrayOfAllMembers([groups objectAtIndex:i]);
NSMutableArray *memberIDs = [[NSMutableArray alloc] initWithCapacity:[members count]];
for (id member in members) {
ABRecordID ID = ABRecordGetRecordID(member);
[memberIDs addObject:[NSNumber numberWithInteger:ID]];
}
[aGroupMembers insertObject:memberIDs atIndex:i];
CFRelease(members);
[memberIDs release];
// Remove the group from the addressbook
ABAddressBookRemoveRecord(abRef, [groups objectAtIndex:i], &error);
}
CFRelease(groups);
ABAddressBookSave(abRef, nil);
self.picker.addressBook = abRef;
}
CFRelease(abRef);
And afterward in both viewWillDisappear and in willResignActive I "attempt" to recreate the groups, re-add the members to each group and add back to the address book. However I'm not able to add the members back, as ABGroupAddMember() fails. Both the GroupName and the firstname of person are correct when I examine variables in the debugger. I cannot see the problem and the CFErrorRef value does not get set.
// Restore the group records.
if (self.aGroups != nil) {
CFErrorRef error = nil;
CFTypeRef grpName = nil;
CFTypeRef firstName = nil;
ABRecordRef newGroup = nil;
ABAddressBookRef abRef = ABAddressBookCreate();
// Re-create the groups
for (int i = 0; i < self.aGroups.count; i++) {
// Create the new group
newGroup = ABGroupCreate();
grpName = ABRecordCopyValue((ABRecordRef)[self.aGroups objectAtIndex:i], kABGroupNameProperty);
ABRecordSetValue(newGroup, kABGroupNameProperty, grpName, &error);
// Create the members
NSArray *memberIDs = (NSArray*)[aGroupMembers objectAtIndex:i];
for (NSNumber *iD in memberIDs) {
ABRecordRef person = ABAddressBookGetPersonWithRecordID(abRef,iD.intValue);
firstName = ABRecordCopyValue((ABRecordRef)person, kABPersonFirstNameProperty);
BOOL bSuccess = ABGroupAddMember(newGroup, person, &error);
if (!bSuccess) {
//NSString *errorStr = [(NSString *)CFErrorCopyDescription(error) autorelease]; // this cause EXEC_BAD_ACCESS
CFRelease(error);
}
}
CFRelease(newGroup);
CFRelease(grpName);
}
// Save the changes
ABAddressBookSave(abRef, nil);
CFRelease(abRef);
self.aGroups = nil;
[aGroupMembers removeAllObjects];
aGroupMembers = nil;
}