从ABAddressBook获取合并/统一的条目

18

我正在开发一个显示iPhone联系人的应用程序。

ABAddressBookRef对于在iPhone联系人应用程序中仅出现一次的联系人返回重复条目。

查看联系人卡片(来自iPhone联系人),底部有一个名为“已链接联系人”的部分,因此显然苹果将这两个条目“合并” / “统一”成为我看到的一个条目。

问题在于如何模仿相同的行为,以便我的应用程序只显示一个条目? 是否有一个API可以从地址簿返回已合并/统一的条目?

2个回答

26
创建一个合并链接联系人的联系人列表:
注意:ABPerson引用存储在自定义的Person类实例中。然后,所有人都存储在字典addressBookDictionary中,使用每个人的recordID作为键。
1. 使用ABAddressBookCopyArrayOfAllPeople获取所有ABPersons。将人员存储在allPersonRecords数组中。
2. 遍历所有ABPersons。
2.1 获取每个ABPerson的链接人列表。使用
ABPersonCopyArrayOfAllLinkedPeople(ABRecordRef person);
如果没有链接联系人,则此方法将返回包括该人自己的数组。因此,如果返回的数组计数> 1,则该人具有链接联系人。
2.2 将链接的联系人添加到NSMutableSet中。这些链接的联系人将被跳过,并且不会在以后的迭代中处理。
2.3 为当前ABPerson创建一个Person实例。
2.4 将链接人信息合并到Person实例中。链接人可能具有不同的电话号码,因此您需要将它们合并在一起。
NSArray *allPersonRecords = (NSArray *) ABAddressBookCopyArrayOfAllPeople(self.addressBook);
NSMutableSet *linkedPersonsToSkip = [[NSMutableSet alloc] init];

for (int i=0; i<[allPersonRecords count]; i++){

    ABRecordRef personRecordRef = [allPersonRecords objectAtIndex:i];

    // skip if contact has already been merged
    //
    if ([linkedPersonsToSkip containsObject:personRecordRef]) {
        continue;
    }

    // Create object representing this person
    //
    Person *thisPerson = [[Person alloc] initWithPersonRef:personRecordRef];

    // check if there are linked contacts & merge their contact information
    //
    NSArray *linked = (NSArray *) ABPersonCopyArrayOfAllLinkedPeople(personRecordRef);
    if ([linked count] > 1) {
        [linkedPersonsToSkip addObjectsFromArray:linked];

        // merge linked contact info
        for (int m = 0; m < [linked count]; m++) {
            ABRecordRef iLinkedPerson = [linked objectAtIndex:m];
            // don't merge the same contact
            if (iLinkedPerson == personRecordRef) {
                continue;
            }
            [thisPerson mergeInfoFromPersonRef:iLinkedPerson];
        }
    }
    [self.addressBookDictionary setObject:thisPerson forKey:thisPerson.recordID];
    [thisPerson release];
    [linked release];
}
[linkedPersonsToSkip release];
[allPersonRecords release];

4
你好,你能描述一下你的代码中Person类包含哪些内容吗? - HarshIT
请描述 - 找不到 Person 类 .. @MinTsai - Ashish Kakkad
Person类只是用于存储每个人联系信息的自定义类,它基本上与我的格式匹配(除了命名)。initWithPersonRef将在personRecordRef上调用AbRecordCopyValue以获取要存储的字段,并将它们保存到Person对象中创建的实例变量/属性中。不要在不理解代码的情况下剪切/粘贴代码,当您实际上需要维护代码时,这将为您带来更大的问题。感谢Harris提供了解决此问题的方案。 - SafeFastExpressive
如果我们有大量的联系人,比如5000个,你认为有更好的方法来实现这个吗?谢谢。 - sole007
方法在哪里?mergeInfoFromPersonRef?还是我们应该自己写? - Sam B
@sole007 我也遇到了同样的问题,这些解决方案并不适用于大规模应用。一旦你超过了2000个联系人,这就变得非常昂贵。在苹果提供本地化的解决方案之前,我感到很无助。 - JRam13

7

您需要查看一个名为:

CFArrayRef ABPersonCopyArrayOfAllLinkedPeople(ABRecordRef person);

这个函数在ABPerson.h中定义。您向该函数传递一个人的ABRecordRef,该函数将返回一个ABRecordRef对象数组,表示链接到您传入的人的通讯录卡。

  1. 对于从ABAddressBookRef返回的包含通讯录条目的数组,进行可变复制。为了讨论,将新数组称为“finalContacts”。

  2. 遍历联系人的原始数组。

  3. 对于数组中的每个条目,请调用上面的函数并传递当前条目。 您将得到一个链接的ABPersonRef对象列表。 从“finalContacts”数组中删除所有这些条目。

  4. 迭代后,“finalContacts”应删除所有链接的卡,并且您应该留下唯一的通讯录卡列表。


听起来还不错..但也许我们应该看看链接联系人有什么好处? - hfossli
同时从列表中删除“mom”、“assistant”和其他链接的显示也听起来很奇怪。 - hfossli
@hfossli: ABPersonCopyArrayOfAllLinkedPeople(person) 返回同一人的其他记录数组。 配偶,助手等链接由ABRecordCopyValue(person,kABPersonRelatedNamesProperty)返回。 - David Hull

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接