【问题标题】:ABPeoplePickerNavigationController customisationABPeoplePickerNavigationController 自定义
【发布时间】:2014-08-14 13:21:28
【问题描述】:

我想使用ABPeoplePickerNavigationController,但我想自定义视图。我想要一些联系人的附件图像,并且我想以与默认方式不同的方式对它们进行排序。有没有办法做到这一点?还是我必须创建自己的UITableViewController

【问题讨论】:

  • 你必须创建自己的UITableViewController
  • You should not need to subclass these controllers; the expected way to modify their behavior is by your implementation of their delegate 这是苹果文档所说的。 developer.apple.com/library/ios/documentation/ContactData/…
  • 同意:如果您想以这种方式自定义联系人的外观,则必须创建自己的表格视图。顺便说一句,如果您正在寻找获取联系人的方法,以便随后对它们进行排序并在您自己的表格视图中显示它们,您可以查看stackoverflow.com/a/23418263/1271826
  • 谢谢。在构建我自己的 UITableViewController 时,有没有办法可以从 ABAddressBook 获取联系人数组,还是必须将它们复制到我自己的数组中?如果是这样,我应该如何复制它们?
  • @Rob 谢谢。我有这个代码来获取联系人数组:ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, nil); self.allContacts = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBookRef); 这对我有用,但是当我在UITableViewController 中显示这个数组时,它看起来没有排序。你知道为什么吗?我以为它会返回一个按联系人姓名字母排序的数组。

标签: ios abaddressbook abpeoplepickerview


【解决方案1】:

如果您想以这种方式自定义联系人的外观,则必须创建自己的表格视图。例如,您可以使用以下方法提取联系人:

- (void)loadContacts
{
    ABAuthorizationStatus status = ABAddressBookGetAuthorizationStatus();

    if (status == kABAuthorizationStatusDenied) {
        // if you got here, user had previously denied/revoked permission for your
        // app to access the contacts, and all you can do is handle this gracefully,
        // perhaps telling the user that they have to go to settings to grant access
        // to contacts

        [[[UIAlertView alloc] initWithTitle:nil message:@"This app requires access to your contacts to function properly. Please visit to the \"Privacy\" section in the iPhone Settings app." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
        return;
    }

    CFErrorRef error = NULL;
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, &error);

    if (error) {
        NSLog(@"ABAddressBookCreateWithOptions error: %@", CFBridgingRelease(error));
        if (addressBook) CFRelease(addressBook);
        return;
    }

    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
        if (error) {
            NSLog(@"ABAddressBookRequestAccessWithCompletion error: %@", CFBridgingRelease(error));
        }

        dispatch_async(dispatch_get_main_queue(), ^{
            if (granted) {
                // if they gave you permission, then get copy of contacts and reload table

                self.allContacts = CFBridgingRelease(ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering(addressBook, NULL, kABPersonSortByLastName));

                [self.tableView reloadData];
            } else {
                // however, if they didn't give you permission, handle it gracefully, for example...

                [[[UIAlertView alloc] initWithTitle:nil message:@"This app requires access to your contacts to function properly. Please visit to the \"Privacy\" section in the iPhone Settings app." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil] show];
            }

            if (addressBook) CFRelease(addressBook);
        });
    });
}

然后你可以在你的cellForRowAtIndexPath 中使用这个数组:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    ABRecordRef person = (__bridge ABRecordRef)self.allContacts[indexPath.row];

    NSMutableArray *nameArray = [NSMutableArray array];

    NSString *prefix    = CFBridgingRelease(ABRecordCopyValue(person, kABPersonPrefixProperty));
    if (prefix) [nameArray addObject:prefix];

    NSString *firstName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty));
    if (firstName) [nameArray addObject:firstName];

    NSString *middleName = CFBridgingRelease(ABRecordCopyValue(person, kABPersonMiddleNameProperty));
    if (middleName) [nameArray addObject:middleName];

    NSString *lastName  = CFBridgingRelease(ABRecordCopyValue(person, kABPersonLastNameProperty));
    if (lastName) [nameArray addObject:lastName];

    NSString *fullname = [nameArray componentsJoinedByString:@" "];

    NSString *suffix    = CFBridgingRelease(ABRecordCopyValue(person, kABPersonSuffixProperty));
    if (suffix) {
        fullname = [NSString stringWithFormat:@"%@, %@", fullname, suffix];
    }

    cell.textLabel.text = fullname;

    NSString *company   = CFBridgingRelease(ABRecordCopyValue(person, kABPersonOrganizationProperty));
    if ([fullname length] == 0) {
        cell.textLabel.text = company;
        cell.detailTextLabel.text = nil;
    } else {
        cell.detailTextLabel.text = company;
    }

    if ([nameArray count] == 0 && [company length] == 0)
        NSLog(@"nothing to show!!!");

    return cell;
}

显然,考虑到整个想法是您想要自定义单元格,请相应地修改 cellForRowAtIndexPath,但希望这能说明这个想法。

【讨论】:

  • 使用此代码时,我发现我的某些联系人会出现两次。我注意到其中一些联系人有 FaceTime。如何设置每个联系人只出现一次?
  • 我刚刚发现在我的桌子上出现两次的联系人是 iPhone 和 iCloud 上的联系人的结果。有没有办法让这些只出现一次?
  • 几个选项: 1. 您可以枚举“来源”,然后让用户选择一个来源,然后获取该来源的所有联系人。 2.您可以手动查找和修剪重复项(但是当您找到重复项时,如果存在细微差异,我不确定您将如何确定哪个“获胜”)。 3.您可以将您的iCloud联系人与您的iPhone联系人合并,这样您就只有一个来源。
  • 1.如何指定要使用的源,源iPhone 和源iCloud 的正确名称是什么? 2. 手动意味着我需要检查每个联系人并将其与所有其他联系人进行比较,对吗?没有更简单的方法可以做到这一点。 3. 合并联系人意味着用户必须在 iPhone 上自己做。或者合并是应用程序只能对您在答案中定义的self.allContacts 执行的操作? (因此它类似于解决方案 2)。
  • 1.您可以使用 ABAddressBookCopyArrayOfAllSources 之类的东西来获取源数组。 2. 是的,手动意味着自己遍历联系人,但如果对它们进行排序,您可能只需将其与先前的记录进行比较,而不是将它们与所有其他联系人进行比较。 3. 是的,我的意思是,如果您(或任何用户)不小心在两个不同的来源中重复了您的联系人,您将自己在 iPhone 上完成该过程。就 iPhone 的适用性而言,在不同来源中进行不必要的欺骗确实很麻烦(很容易忘记您正在处理的是哪一个)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-22
相关资源
最近更新 更多