Цель отображаемого имени CNContact c / swift

Я работаю над приложением, в котором мне нужно импортировать контакты в NSMutableDictionary, но иногда люди не заполняют все контактные данные. Поэтому оставляем только номер или название компании. Нужно ли мне просматривать все детали контактов, чтобы проверить, какое поле будет моим «отображаемым именем». В Android я знаю, что есть переменная displayName. Но как это в Swift или Objective C?

Мой код:

 BOOL success = [addressBook
  enumerateContactsWithFetchRequest:request   
                              error:&contactError       
                         usingBlock:^(CNContact *contact, BOOL *stop){

        NSString * contactId = contact.identifier;
        NSString * firstName = contact.givenName;
        NSString * lastName  = contact.familyName;
                 }];

person David Chelidze    schedule 26.04.2016    source источник


Ответы (3)


Используйте CNContactFormatter для создания отображаемого имени. При указании ключей для запроса используйте descriptorForRequiredKeysForStyle, чтобы убедиться, что вы запросили соответствующие поля.

В Swift это будет:

let store = CNContactStore()
store.requestAccess(for: .contacts) { granted, error in
    guard granted else {
        print(error?.localizedDescription ?? "Unknown error")
        return
    }

    let request = CNContactFetchRequest(keysToFetch: [CNContactIdentifierKey as CNKeyDescriptor, CNContactFormatter.descriptorForRequiredKeys(for: .fullName)])

    let formatter = CNContactFormatter()
    formatter.style = .fullName

    do {
        try store.enumerateContacts(with: request) { contact, stop in
            if let name = formatter.string(from: contact) {
                print(name)
            }
        }
    } catch let fetchError {
        print(fetchError)
    }
}

Вы предположили, что у вас бывают ситуации, когда нет ни имени, ни фирмы, а просто номер телефона. Ну, тогда вам придется вручную обрабатывать это самостоятельно:

let request = CNContactFetchRequest(keysToFetch: [CNContactIdentifierKey as CNKeyDescriptor, CNContactPhoneNumbersKey as CNKeyDescriptor, CNContactFormatter.descriptorForRequiredKeys(for: .fullName)])

do {
    try store.enumerateContacts(with: request) { contact, stop in
        if let name = formatter.string(from: contact) {
            print(name)
        } else if let firstPhone = contact.phoneNumbers.first?.value {
            print(firstPhone.stringValue)
        } else {
            print("no name; no number")
        }
    }
} catch let fetchError {
    print(fetchError)
}

Для Swift 2 см. предыдущую версию этого ответа.

person Rob    schedule 26.04.2016
comment
как проверить это .fullName доступно или нет ..? мы можем использовать это с isKeyAvilable? - person Surjeet Rajput; 01.09.2016
comment
IIRC, .FullName был доступен с первой версией платформы контактов, поэтому я не думаю, что есть необходимость проверять доступность. Возможно, вы захотите выполнить дополнительную привязку stringFromContact (например, if let fullName = formatter.stringFromContact(contact) { ... }). Вы также можете добавить проверку, чтобы убедиться, что fullName != "" там тоже есть, хотя я подозреваю, что это не нужно. - person Rob; 01.09.2016

Вы можете получить имя контакта из своей телефонной книги, используя этот код: -

- (void) fetchContacts
{
    CNAuthorizationStatus status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
    if (status == CNAuthorizationStatusDenied || status == CNAuthorizationStatusDenied) {
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"This app previously was refused permissions to contacts; Please go to settings and grant permission to this app so it can use contacts" preferredStyle:UIAlertControllerStyleAlert];

        [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
        [self presentViewController:alert animated:TRUE completion:nil];
        return;
    }

    CNContactStore *store = [[CNContactStore alloc] init];    [store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {

        // make sure the user granted us access

        if (!granted) {
            dispatch_async(dispatch_get_main_queue(), ^{
                // user didn't grant access;
                // so, again, tell user here why app needs permissions in order  to do it's job;
                // this is dispatched to the main queue because this request could be running on background thread
            });
            return;
        }

        // build array of contacts

        NSMutableArray *contacts = [NSMutableArray array];

        NSError *fetchError;
        CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[CNContactIdentifierKey, [CNContactFormatter descriptorForRequiredKeysForStyle:CNContactFormatterStyleFullName]]];

        BOOL success = [store enumerateContactsWithFetchRequest:request error:&fetchError usingBlock:^(CNContact *contact, BOOL *stop) {
            [contacts addObject:contact];
        }];



        if (!success) {
            NSLog(@"error = %@", fetchError);
        }



        // you can now do something with the list of contacts, for example, to show the names

        CNContactFormatter *formatter = [[CNContactFormatter alloc] init];

        for (CNContact *contact in contacts) {
            if (!_contacts) {
                _contacts = [[NSMutableArray alloc] init];
            }

            NSString *string = [formatter stringFromContact:contact];
            NSLog(@"contact = %@", string);
            [_contacts addObject:string];
        }
        [_contactatableview reloadData];

    }];
}
person Community    schedule 26.04.2016

Получение контактов с устройств

if (isIOS9) { //checking iOS version of Device

    CNContactStore *store = [[CNContactStore alloc] init];

    //keys with fetching properties
    NSArray *keys = @[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactEmailAddressesKey,CNContactPostalAddressesKey, CNLabelWork, CNLabelDateAnniversary];

    NSString *containerId = store.defaultContainerIdentifier;

    NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
    NSError *error;
    NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
    DLOG(@"cnContacts %lu",(unsigned long)cnContacts.count);

    if (error) {
        //error
    } else {

        for (CNContact *contact in cnContacts) {

            //iterate over cnContacts to get details
        }

    }

} else {

    //for below iOS 9
    ABAddressBookRef addressBook = ABAddressBookCreate();

    CFArrayRef arrPersons = ABAddressBookCopyArrayOfAllPeople(addressBook);
    CFIndex count = ABAddressBookGetPersonCount(addressBook);
    NSLog(@"cnContacts %lu",(unsigned long)count);

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

        ABRecordRef record = CFArrayGetValueAtIndex(arrPersons,i);

        //use kABPersonBirthdayProperty to get b’day
        NSString *birthDay = (__bridge NSString *)(ABRecordCopyValue(record, kABPersonBirthdayProperty));
        NSLog(@“B’day %@”, birthDay);
    }

}
person Mahendra    schedule 26.04.2016
comment
Вы должны запросить разрешение. Кроме того, в вашем коде ABAddressBook есть утечки. - person Rob; 26.04.2016