与 ABAddressBook 的重复联系

Duplicate contact with ABAddressBook

我正在使用 ABAddressBook,我可以显示每个联系人,但我有一些重复的联系人。

我已阅读此主题:Dealing with duplicate contacts due to linked cards in iOS' Address Book API,但无法解决问题。

我想在我的代码中使用这个代码,但我没有成功..:[=​​13=]

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];

这是我的代码:

- (void)getPersonOutOfAddressBook
{
    //1
    CFErrorRef error = NULL;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);

    if (addressBook != nil) {
        NSLog(@"Succesful.");

        //2
        NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);


        //3
        NSUInteger i = 0; for (i = 0; i < [allContacts count]; i++)
        {
            Person *person = [[Person alloc] init];
            ABRecordRef contactPerson = (__bridge ABRecordRef)allContacts[i];

            //4
            NSString *firstName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson,
                                                                                  kABPersonFirstNameProperty);
            if (firstName == nil)
            {
                firstName = @"";
            }
            NSString *lastName = (__bridge_transfer NSString *)ABRecordCopyValue(contactPerson, kABPersonLastNameProperty);
            if (lastName == nil)
            {
                lastName = @"";
            }
            NSString *fullName = [NSString stringWithFormat:@"%@ %@", firstName, lastName];

            person.firstName = firstName; person.lastName = lastName;
            person.fullName = fullName;



            //phone
            //5
            ABMultiValueRef phones = ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);

            //6
            NSUInteger j = 0;
            for (j = 0; j < ABMultiValueGetCount(phones); j++) {
                NSString *phone = (__bridge_transfer NSString *)ABMultiValueCopyValueAtIndex(phones, j);

                if (j == 0) {
                    person.mainNumber = phone;
                }
                else if (j==1) person.secondNumber = phone;
            }

            //7
            [person.mainNumber stringByReplacingOccurrencesOfString:@" " withString:@""];
            [person.mainNumber stringByReplacingOccurrencesOfString:@"(" withString:@""];
            [person.mainNumber stringByReplacingOccurrencesOfString:@")" withString:@""];
            [person.mainNumber stringByReplacingOccurrencesOfString:@"+336" withString:@"06"];
            [self.tableData addObject:person];
            [self.contact addObject:person.fullName];

        }

        //8
        CFRelease(addressBook);
    } else {
        //9
        NSLog(@"Error reading Address Book");
    }
    NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"fullName" ascending:YES];
    [self.tableData sortUsingDescriptors:[NSArray arrayWithObject:sorter]];

}

如果您想避免添加重复项,最简单的方法可能是构建一组已添加内容的 ABRecordID 值,并且仅在该集合中不存在联系人时才添加联系人:

self.tableData = [NSMutableArray array];
NSMutableSet *foundIDs = [NSMutableSet set];

NSArray *allContacts = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));

for (id record in allContacts) {
    ABRecordRef contactPerson = (__bridge ABRecordRef)record;
    ABRecordID recordId = ABRecordGetRecordID(contactPerson);
    if (![foundIDs containsObject:@(recordId)]) {
        Person *person = [[Person alloc] init];

        // get name

        person.firstName = CFBridgingRelease(ABRecordCopyValue(contactPerson, kABPersonFirstNameProperty)) ?: @"";
        person.lastName = CFBridgingRelease(ABRecordCopyValue(contactPerson, kABPersonLastNameProperty)) ?: @"";
        person.fullName = [NSString stringWithFormat:@"%@ %@", person.firstName, person.lastName];

        // get phones

        ABMultiValueRef phones = ABRecordCopyValue(contactPerson, kABPersonPhoneProperty);
        for (NSUInteger j = 0; j < ABMultiValueGetCount(phones); j++) {
            // I presume you meant to use mutable string and `replaceOccurrencesOfString`:

            NSMutableString *phone = [CFBridgingRelease(ABMultiValueCopyValueAtIndex(phones, j)) mutableCopy];

            [phone replaceOccurrencesOfString:@" "    withString:@""   options:0 range:NSMakeRange(0, phone.length)];
            [phone replaceOccurrencesOfString:@"("    withString:@""   options:0 range:NSMakeRange(0, phone.length)];
            [phone replaceOccurrencesOfString:@")"    withString:@""   options:0 range:NSMakeRange(0, phone.length)];
            [phone replaceOccurrencesOfString:@"+336" withString:@"06" options:0 range:NSMakeRange(0, phone.length)];

            if (j == 0)     person.mainNumber   = phone;
            else if (j==1)  person.secondNumber = phone;
        }
        CFRelease(phones);

        // add the `Person` record

        [self.tableData addObject:person];

        // add the ID for this person (and all linked contacts) to our set of `foundIDs`

        NSArray *linkedPeople = CFBridgingRelease(ABPersonCopyArrayOfAllLinkedPeople(contactPerson));
        if (linkedPeople) {
            for (id record in linkedPeople) {
                [foundIDs addObject:@(ABRecordGetRecordID((__bridge ABRecordRef)record))];
            }
        } else {
            [foundIDs addObject:@(recordId)];
        }
    }
}

CFRelease(addressBook);

NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"fullName" ascending:YES];
[self.tableData sortUsingDescriptors:@[descriptor]];

话虽如此,您可能应该遍历所有链接的联系人并在那里查找 phone 号码。也许也可以对名称进行一些验证(例如,如果您有一个 J. D. Salinger 的条目,另一个 John David Salinger 的条目,则可以使用一些算法来确定您要使用哪个名称)。你可以做很多事情。但是上面说明了一个简约的解决方案,它将联系人和任何链接的联系人添加到已找到的联系人列表中。