CNContactStore количество записей контактов

Мне нужно получить количество всех контактов на устройстве пользователя. В сообщении об устаревании ABAddressBookGetPersonCount говорится:

использовать количество результатов выборки для CNContactFetchRequest с предикатом = nil

Вот что я сделал, следуя этому руководству:

 __block NSUInteger contactsCount = 0;

NSError *error;
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[CNContactGivenNameKey]];
BOOL success = [self.contactStore enumerateContactsWithFetchRequest:request error:&error
                                                         usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
                                                             contactsCount += 1;
                                                         }];
if (!success || error) {
    NSLog(@"error counting all contacts, error - %@", error.localizedDescription);
}

Однако это выглядит ужасно с точки зрения производительности. Я не нашел другого способа подсчета без перечисления объектов CNContact. Я что-то упускаю?

Заранее спасибо!


person i-konov    schedule 18.04.2016    source источник
comment
Чем ваш код похож на предложение в сообщении об устаревании?   -  person trojanfoe    schedule 18.04.2016
comment
Есть ли другой способ выполнить CNContactFetchRequest?   -  person i-konov    schedule 18.04.2016


Ответы (2)


Это старо, но на случай, если кто-то еще наткнется на это, это можно сделать, выполнив перечисление с 0 ключами для выборки вместо 1.

__block NSUInteger contactsCount = 0;

NSError *error;
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[]];
BOOL success = [self.contactStore enumerateContactsWithFetchRequest:request error:&error
                                                     usingBlock:^(CNContact * _Nonnull contact, BOOL * _Nonnull stop) {
                                                         contactsCount += 1;
                                                     }];
if (!success || error) {
   NSLog(@"error counting all contacts, error - %@", error.localizedDescription);
}

С 0 ключами я смог запустить подсчет на устройстве с 10 000 контактов за 0,8 секунды (тогда как с 1 ключом это заняло 14 секунд).

person haplo1384    schedule 19.04.2017
comment
Это на самом деле очень хороший момент! Я все еще хочу, чтобы Apple добавила законный способ подсчета. Ingurss простое кешированное свойство было бы единственным правильным способом. Еще раз спасибо за понимание. - person i-konov; 21.04.2017

Версия Swift 3, упакованная как функция класса.

class func contactCount() -> Int? {
    let contactStore = CNContactStore()
    var contactsCount: Int = 0
    let contactFetchRequest = CNContactFetchRequest(keysToFetch: [])
    do {
        try contactStore.enumerateContacts(with: contactFetchRequest) { (contact, error) in
        contactsCount += 1
        }
    } catch {
        print("Error counting all contacts.\nError: \(error)")
        return nil
    }

    return contactsCount
}

Часто будет лучше повторно использовать хранилище контактов, чем создавать другое:

class func contactCount(store: CNContactStore?) -> Int? {
    let contactStore: CNContactStore

    if let suppliedStore = store {
        contactStore = suppliedStore
    } else {
        contactStore = CNContactStore()
    }

    var contactsCount: Int = 0
    let contactFetchRequest = CNContactFetchRequest(keysToFetch: [])
    do {
        try contactStore.enumerateContacts(with: contactFetchRequest) { (contact, error) in
        contactsCount += 1
        }
    } catch {
        print("Error counting all contacts.\nError: \(error)")
        return nil
    }

    return contactsCount
} 
person Duncan Babbage    schedule 29.06.2017