my application reads the Iphone AddressBook and will receive email and phone numbers for each contact. After this process, I store this information in my database and create an object that I store in NSMutableArray for the following purpose. I perform this operation only the first time the user launches the application. When I have a small AddressBook (<500 contacts), it works like a charme, and I have a reasonable wait time (about 1 minute), but with a lot of contacts (> 2000) I have excessive waiting time and poor performance (about 3 ,4 minutes). Although this task is performed in the background thread, there is some way to optimize this import phase (maybe import multiple contacts at the same time?).
This is my code to run. Import process:
-(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];
}
And this is the code for importing Process:
+(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;
}