如何告诉ABPeoplePickerNavigationController仅列出具有电子邮件地址的联系人?

时间:2012-09-22 15:54:20

标签: ios filter contacts addressbook

我希望我的用户通过从地址簿中选择联系人的电子邮件来填写电子邮件字段。我不希望他们滚动所有未设置电子邮件的联系人,所以我想过滤那些有电子邮件地址的联系人。

这是我到目前为止编写的代码。我可以找出谁有一个电子邮件地址,谁没有,但我不能告诉ABPeoplePickerNavigationController只列出正确的联系人。是不可能实现这一点,我的意思是我必须使用表格视图来实现我自己的联系人选择器类,或者这段代码是否有问题?

ABAddressBookRef addressBook = ABAddressBookCreate();
NSArray *peopleList = (NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook);
NSLog(@"%ld people exist in the addressBook", ABAddressBookGetPersonCount(addressBook));
for (id peopleRecord in peopleList) {
    ABMultiValueRef mv = ABRecordCopyValue((ABRecordRef)peopleRecord, kABPersonEmailProperty);
    CFIndex numberOfAddresses = ABMultiValueGetCount(mv);
    if(numberOfAddresses == 0) {
        CFErrorRef err;
        ABAddressBookRemoveRecord( addressBook, (ABRecordRef)peopleRecord, &err);
    }
}
[peopleList release];

NSLog(@"%ld people have an email", ABAddressBookGetPersonCount(addressBook));

ABPeoplePickerNavigationController *peoplePicker = [[ABPeoplePickerNavigationController alloc] init];
NSNumber* emailProp = [NSNumber numberWithInt:kABPersonEmailProperty];
[peoplePicker setAddressBook:addressBook];
peoplePicker.displayedProperties = [NSArray arrayWithObject:emailProp];
[peoplePicker setPeoplePickerDelegate:self];
[self presentModalViewController:peoplePicker animated:YES];

2 个答案:

答案 0 :(得分:15)

我知道这已经过时了,但我在研究相关主题时偶然发现了这一点,所以我想我会用我的发现更新这个。

  1. 虽然它不会过滤结果,但值得注意的是,iOS 8具有禁用没有电子邮件地址的联系人的功能:

    peoplePickerController.predicateForEnablingPerson = [NSPredicate predicateWithFormat:@"emailAddresses.@count > 0"];
    

    您仍会看到所有联系人,但至少禁用那些没有电子邮件地址的联系人。显然,如果您的最低目标操作系统早于iOS 8,那么您将有条件地执行上述操作:

    if ([peoplePickerController respondsToSelector:@selector(predicateForEnablingPerson)]) {
        peoplePickerController.predicateForEnablingPerson = [NSPredicate predicateWithFormat:@"emailAddresses.@count > 0"];
    }
    
  2. 如果您要过滤掉没有地址的条目,您必须为此提供自己的用户界面(例如创建自己的桌面视图)。因此,首先,使用如下所示的电子邮件地址构建您自己的联系人数组:

    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
        if (granted) {
            NSArray *allPeople = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeople(addressBook));
            NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id person, NSDictionary *bindings) {
                ABMultiValueRef emails = ABRecordCopyValue((__bridge ABRecordRef)person, kABPersonEmailProperty);
                NSInteger count = ABMultiValueGetCount(emails);
                CFRelease(emails);
                return count > 0;
            }];
    
            NSArray *peopleWithEmails = [allPeople filteredArrayUsingPredicate:predicate];
    
            // You now have an array of `ABRecordRef` associated with 
            // those contacts with email addresses. You can use this as 
            // the model backing your own table view, or populate your
            // own model.
        } else {
            NSLog(@"Access not granted");
            if (error) {
                CFRelease(error);
            }
        }
    });
    

    完成后,您可以构建自己的tableview,列出peopleWithEmails的相关详细信息。

答案 1 :(得分:1)

我不相信有办法让iOS进行这种过滤。我也是在代码中做的。请注意,您需要查找各种电子邮件地址 - 您必须遍历您可以获得的字典。使用它是一个PITA肯定 - 我以前做过 - 你必须小心不要有内存泄漏。

我所做的就像你建议的那样 - 我自己遍历所有联系人,然后我用表格弹出一个视图,然后选择他们想要的人的名字。我保持联系,所以我知道什么地址与什么名称相关联,然后使用系统电子邮件框架,然后填充发送地址。