One method would be to only retrieve the contacts from the default address book source:
ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *people = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeopleInSource(addressBook, ABAddressBookCopyDefaultSource(addressBook));
But that is lame, right? It targets the on-device address book, but not extra contacts that might be in Exchange or other fancy syncing address books.
So here’s the solution you’re looking for:
- Iterate through the ABRecord references
- Grab each respective “linked references” (using
ABPersonCopyArrayOfAllLinkedPeople
) - Bundle them in an NSSet (so that the grouping can be uniquely identified)
- Add that NSSet to another NSSet
- Profit?
You now have an NSSet containing NSSets of linked ABRecord objects. The overarching NSSet will have the same count as the number of contacts in your “Contacts” app.
Example code:
NSMutableSet *unifiedRecordsSet = [NSMutableSet set];
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef records = ABAddressBookCopyArrayOfAllPeople(addressBook);
for (CFIndex i = 0; i < CFArrayGetCount(records); i++)
{
NSMutableSet *contactSet = [NSMutableSet set];
ABRecordRef record = CFArrayGetValueAtIndex(records, i);
[contactSet addObject:(__bridge id)record];
NSArray *linkedRecordsArray = (__bridge NSArray *)ABPersonCopyArrayOfAllLinkedPeople(record);
[contactSet addObjectsFromArray:linkedRecordsArray];
// Your own custom "unified record" class (or just an NSSet!)
DAUnifiedRecord *unifiedRecord = [[DAUnifiedRecord alloc] initWithRecords:contactSet];
[unifiedRecordsSet addObject:unifiedRecord];
CFRelease(record);
}
CFRelease(records);
CFRelease(addressBook);
_unifiedRecords = [unifiedRecordsSet allObjects];