Как быстрее получать контакты iOS с помощью структуры контактов Apple с длинным списком контактов?

Я использую CNContacts для получения контактов телефонной книги на своем устройстве iOS.

Когда у меня в телефоне небольшое количество контактов (скажем, 50), контакты извлекаются легко.

Однако, когда у меня много контактов (скажем, 500-700), он зависает/ожидает в течение длительного времени, чтобы извлечь эти контакты из телефонной книги iOS в массив моего приложения.

Раньше я использовал https://github.com/Alterplay/APAddressBook, которая была быстрой библиотекой для предыдущей версии Apple. framework, но теперь я использую последнюю версию Apple framework.

Мой код для получения контактов ....

#pragma mark - Get All Contacts....

-(void)getAllContactsWithNewFrameworkOfApple {

    NSMutableArray *_contactsArray = [[NSMutableArray alloc]init];

    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;
        }

        NSError *fetchError;
        CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:@[CNContactIdentifierKey,CNContactGivenNameKey,CNContactFamilyNameKey,CNContactEmailAddressesKey,CNContactPhoneNumbersKey]];

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

            [_contactsArray addObject:contact];
            NSLog(@"I am %@", _contactsArray);

        }];

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

                        NSLog(@"End with Success %@", _contactsArray);
            [self finalUsage:_contactsArray];

        }

    }];



}

Я пытался получить контакты партиями по 20, каждый раз перезагружая таблицу. Однако здесь он не может перезагрузиться в потоке отправки или просто падает.

Как улучшить этот код, чтобы быстро получать контакты?

Спасибо.


person Sam Shaikh    schedule 09.11.2015    source источник
comment
Я думаю, что вы можете получить контакты в дочернем потоке, но при перезагрузке таблицы она должна запускаться в основном потоке. Вылетает из-за перезагрузки таблицы в дочернем потоке.   -  person AechoLiu    schedule 09.11.2015


Ответы (1)


Как упоминал Торо, метод requestAccessForEntityType: completionHandler: не работает в основном (UI) потоке. Из документация, вы можете увидеть, что в ней упоминается следующее:

Пользователи могут предоставлять или запрещать доступ к контактным данным для каждого приложения. Запросите доступ к контактным данным, вызвав метод requestAccessForEntityType:completionHandler:. Это не заблокирует ваше приложение, пока у пользователя запрашивается разрешение. Пользователю будет предложено только при первом запросе доступа; любые последующие вызовы CNContactStore будут использовать существующие разрешения. Обработчик завершения вызывается для произвольной очереди. Рекомендуется использовать методы экземпляра CNContactStore в этом обработчике завершения вместо основного потока пользовательского интерфейса. Этот метод является необязательным, если CNContactStore используется в фоновом потоке. Если этот метод не используется, CNContactStore может заблокировать ваше приложение, пока у пользователя запрашивается разрешение на доступ.

Поэтому любые обновления, которые вы хотите сделать в пользовательском интерфейсе, вам придется делать в основном потоке.

dispatch_async(dispatch_get_main_queue(), ^{
   //Update UI on the Main thread, like reloading a UITableView
});
person Lefteris    schedule 09.11.2015