【问题标题】:Duplicate contact with ABAddressBook与 ABAddressBook 重复联系
【发布时间】:2015-08-19 20:30:38
【问题描述】:

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

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

我想在我的中使用此代码,但我没有成功..:

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

}

【问题讨论】:

  • 不相关,但是虽然您已经修复了原版的一些内存泄漏,但引入了您自己的一个:您必须CFRelease(phones)。此外,您在主电话号码中进行了一些字符串替换,但没有对这些替换做任何事情,将它们丢弃。如果你想这样做,可变字符串可能是有意义的。
  • @Rob 我又遇到了一些问题,我使用 self.contact (NSMutableArray) 仅添加 fullName 以便按部分进行排序。我更新了我的代码以向您展示这一点。我不知道如何仅使用 ViewDidLoad 中的 self.tableData 进行修复。对于localizedCaseInsensitiveCompare,我只需要访问person.fullName
  • @Rob 好的,完成。非常感谢您的帮助!!!

标签: ios objective-c nsarray abaddressbook nsset


【解决方案1】:

如果您想避免添加重复项,最简单的方法可能是构建一组已添加内容的 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]];

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

【讨论】:

  • 非常感谢罗伯!!!你救了我的命?,我可以用你的 cmets 理解一切!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-09
  • 2013-01-28
相关资源
最近更新 更多