2

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;
}
ekad
  • 14,436
  • 26
  • 44
  • 46
imobilizer
  • 161
  • 1
  • 13

2 Answers2

2

This happened to me when trying to add contacts that were synced to my iPhone from Google via CardDAV protocol, to a local group, created programatically.

It turns out you can't add synced-in contacts to local groups or vice versa, but it simply returns NO without setting the error param to any error message to explain why it didn't work.

I solved it in my app by trying to add the contact to the group, and if it doesn't work I workaround it by saving the contact-group relationship locally in my app.

Not that great, if anyone has a way to solve this I'd be happy to hear.

marmor
  • 27,641
  • 11
  • 107
  • 150
1

You might need to add the group record to the address book with ABAddressBookAddRecord before trying to add members to the group with ABGroupAddMember.

snb
  • 171
  • 5
  • I had the same problem with the simulator: In order to add contacts to a new group, I had to add the empty group to the address book first, then to save and re-open the address book, and only then add contacts to new new group. It did not work when I did not save the address book before adding the contacts to new new group. – Reinhard Männer Jan 25 '14 at 09:25