Цель c алгоритмом импорта адресной книги со многими контактами
Мое приложение читает Iphone AddressBook и для каждого контакта получает электронную почту и номера телефонов. После этого процесса я сохраняю эту информацию в своей базе данных и создаю объект, который храню в NSMutableArray для следующей цели. Я выполняю эту операцию только при первом запуске приложения пользователем. Когда у меня небольшая адресная книга ( < 500 контактов), это работает как чудо, и у меня разумное время ожидания (около 1 минуты), но с большим количеством контактов ( > 2000) у меня чрезмерное время ожидания и плохая производительность (около 3,4 минуты). Хотя эта задача выполняется в фоновом потоке, существует какой-либо способ оптимизировать этот этап импорта (возможно, импорт нескольких контактов одновременно?).
Это мой код для запуска процесса импорта:
-(void)importaContatti:(int32_t)lastIDContatto {
[self beginBackgroundUpdateTask:&importContattiTaskIdentifier];
ABAddressBookRef addressBook;
if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0) {
addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
ABAddressBookRequestAccessWithCompletion(addressBook,
^(bool granted, CFErrorRef error){
dispatch_semaphore_signal(sema);
});
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
} else {
addressBook = ABAddressBookCreate();
}
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
if(nPeople == 0) {
[[Database getIstance]insertBGPhoneData:@"importContatti" val:@"1"];
CFRelease(addressBook);
[self endBackgroundUpdateTask:&importContattiTaskIdentifier];
return;
}
for ( int i = 0; i < nPeople; i++ ) {
ABRecordRef ref = CFArrayGetValueAtIndex( allPeople, i );
int32_t idIphone = ABRecordGetRecordID(ref);
if(idIphone <= lastIDContatto) {
continue;
}
Contatto *c = [Contatto buildContattoFromRubricaIphone:&ref];
CFRelease(ref);
c = NULL;
[[Database getIstance]insertBGPhoneData:@"lastImportContatto" val:[NSString stringWithFormat:@"%d", idIphone ]];
}
[[Database getIstance]insertBGPhoneData:@"importContatti" val:@"1"];
if(allPeople) {
CFRelease(allPeople);
}
[self endBackgroundUpdateTask:&importContattiTaskIdentifier];
}
И это код для процесса импорта:
+(Contatto *)buildContattoFromRubricaIphone:(ABRecordRef *)ref {
int32_t idIphone = ABRecordGetRecordID(*ref);
Contatto *c = [Contatto create];
CFStringRef nome = ABRecordCopyValue(*ref, kABPersonFirstNameProperty);
CFStringRef cognome = ABRecordCopyValue(*ref, kABPersonLastNameProperty);
NSString *alias = [[Utils getIstance]buildAlias:(__bridge NSString *)nome cognome:(__bridge NSString *)cognome];
c.rubrica2 = [Rubrica2 build:0 idIphone:idIphone alias:alias img:NULL stato:ATTIVO jidPreferito:0 mergedWith:0 imgUpdated:0 personalStatus:0 xmppStatus:@"" xmppMood:NESSUNO xmppDisponibilita:@""];
if(nome) {
CFRelease(nome);
}
if(cognome) {
CFRelease(cognome);
}
[c.rubrica2 save];
Rubrica_TEL *telForAlias = NULL;
Rubrica_MAIL *mailForAlias = NULL;
for(NSString *numeroTelefono in [Contatto getNumeriContattoFromRubricaIphone:ref]) {
Rubrica_TEL *tel = [Rubrica_TEL build:0 idRubrica:c.rubrica2.ID telefono:numeroTelefono tipo:0 stato:ATTIVO prevMerged:0];
[tel saveWithNotification:false];
if(telForAlias == NULL) {
telForAlias = tel;
}
[c add:tel];
}
for(NSString *stringMail in [Contatto getEmailFromRubricaIphone:ref]) {
Rubrica_MAIL *mail = [Rubrica_MAIL build:0 rubricaID:c.rubrica2.ID mailID:stringMail mailAlias:alias];
[mail saveWithNotification:false];
if(mailForAlias == NULL) {
mailForAlias = mail;
}
[c add:mail];
}
if([c.rubrica2.alias length] == 0) {
if(telForAlias != NULL) {
c.rubrica2.alias = telForAlias.telefono;
} else if(mailForAlias != NULL) {
c.rubrica2.alias = mailForAlias.mail;
}
if([c.rubrica2.alias length] > 0) {
[c.rubrica2 save];
}
}
return c;
}
С этим методом я получаю телефон от контакта адресной книги (электронная почта подобна):
+(NSMutableArray *)getNumeriContattoFromRubricaIphone:(ABRecordRef *)ref {
NSMutableArray *result = [[NSMutableArray alloc]init];
ABMultiValueRef *phones = ABRecordCopyValue(*ref, kABPersonPhoneProperty);
for(CFIndex j = 0; j < ABMultiValueGetCount(phones); j++) {
CFStringRef phoneNumberRef = ABMultiValueCopyValueAtIndex(phones, j);
NSString *phoneNumber = (__bridge NSString *)phoneNumberRef;
if(phoneNumber != NULL) {
phoneNumber = [[Utils getIstance]formatE164:phoneNumber];
[result addObject:phoneNumber];
}
if(phoneNumberRef) {
CFRelease(phoneNumberRef);
}
}
if(phones) {
CFRelease(phones);
}
return result;
}