Настройка ABPeoplePickerNavigationController

Я хочу использовать ABPeoplePickerNavigationController, но хочу настроить представление. Я хочу, чтобы у некоторых контактов было вспомогательное изображение, и я хочу отсортировать их иначе, чем по умолчанию. Есть ли способ сделать это? Или мне нужно создать свой собственный UITableViewController?


person bobsacameno    schedule 14.08.2014    source источник
comment
Вы должны создать свой собственный UITableViewController   -  person Mohit    schedule 14.08.2014
comment
You should not need to subclass these controllers; the expected way to modify their behavior is by your implementation of their delegate это то, что говорится в документе Apple. developer.apple.com/library/ios/documentation/ContactData/   -  person Mohit    schedule 14.08.2014
comment
Согласен: вам придется создать собственное табличное представление, если вы хотите настроить внешний вид контактов таким образом. Кстати, если вы ищете способы получить контакты, чтобы впоследствии их можно было отсортировать и отобразить в своем собственном табличном представлении, вы можете увидеть stackoverflow.com/a/23418263/1271826.   -  person Rob    schedule 14.08.2014
comment
Спасибо. При создании собственного UITableViewController есть ли способ получить массив контактов из ABAddressBook или мне нужно скопировать их в свой собственный массив? Если да, то как мне их скопировать?   -  person bobsacameno    schedule 14.08.2014
comment
@Роб Спасибо. У меня есть этот код для получения массива контактов: ABAddressBookRef addressBookRef = ABAddressBookCreateWithOptions(NULL, nil); self.allContacts = (__bridge NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBookRef); Это работает для меня, но когда я отображаю этот массив в UITableViewController, он выглядит не отсортированным. Ты знаешь почему? Я думал, что он вернет массив, отсортированный по алфавиту имен контактов.   -  person bobsacameno    schedule 14.08.2014
comment
Во-первых, используйте __bridge_transfer (или CFBridgingRelease), а не __bridge, иначе ваше приложение будет просачиваться. Во-вторых, вы можете сортировать, если используете ABAddressBookCopyArrayOfAllPeopleInSourceWithSortOrdering. Или просто отсортируйте массив самостоятельно, используя одну из многочисленных процедур сортировки, например sortedArrayUsingComparator.   -  person Rob    schedule 14.08.2014


Ответы (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, но, надеюсь, это иллюстрирует идею.

person Rob    schedule 14.08.2014
comment
При использовании этого кода я получаю, что некоторые из моих контактов вижу дважды. Я заметил, что у некоторых из этих контактов есть FaceTime. Как я могу настроить, чтобы каждый контакт отображался только один раз? - person bobsacameno; 17.08.2014
comment
Я только что понял, что контакты, дважды появляющиеся на моем столе, являются результатом того, что они являются контактами на iPhone и в iCloud. Есть ли способ заставить их появляться только один раз? - person bobsacameno; 18.08.2014
comment
Несколько вариантов: 1. Вы можете перечислить источники, а затем позволить пользователю выбрать источник, а затем получить все контакты для этого источника. 2. Вы можете вручную найти и удалить дубликаты (но когда вы найдете дубликат, я не уверен, как вы определите, какой из них победит, если есть незначительные различия). 3. Вы можете объединить свои контакты iCloud с контактами iPhone, чтобы у вас был только один источник. - person Rob; 18.08.2014
comment
1. Как указать, какой источник использовать, и какое правильное имя для источника iPhone и источника iCloud? 2. Вручную означает, что мне нужно просмотреть каждый контакт и сравнить его со всеми остальными контактами, верно? Нет более простого способа сделать это. 3. объединение контактов означает, что пользователь должен сделать это на самом iPhone. Или слияние — это то, что приложение может делать только для self.allContacts, которое вы определили в ответе? (и поэтому это будет что-то вроде решения 2). - person bobsacameno; 18.08.2014
comment
1. Вы должны использовать что-то вроде ABAddressBookCopyArrayOfAllSources для получения массива источников. 2. Да, вручную означает повторение контактов самостоятельно, хотя, если они отсортированы, вы, вероятно, можете просто сравнить их с предыдущей записью, а не сравнивать их со всеми другими контактами. 3. Да, я имел в виду, что если ваши контакты (или любой пользователь) случайно продублировались в двух разных источниках, вы сами пройдете этот процесс на своем iPhone. С точки зрения жизнеспособности iPhone наличие ненужных дубликатов в разных источниках — настоящая проблема (легко забыть, над каким из них вы работаете). - person Rob; 18.08.2014