I have some code to copy contacts from Addreesbook. It works perfectly if there is a small number of contacts. Now In my phone there us 1200 contacts and the app crashes when I tried to copy them. Can anyone help me to optimize this code or rewrite code? The code I am using is added below:
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
NSString *requestContactsString = @"<contacts>";
for (int i=0; i<nPeople; i++)
{
NSLog(@"Started : %d", i);
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
CFTypeRef firstName = ABRecordCopyValue(ref, kABPersonFirstNameProperty);
CFTypeRef lastName = ABRecordCopyValue(ref, kABPersonLastNameProperty);
CFTypeRef email = ABRecordCopyValue(ref, kABPersonEmailProperty);
CFTypeRef phone = ABRecordCopyValue(ref, kABPersonPhoneProperty);
requestContactsString = [requestContactsString stringByAppendingFormat:@"<item>"];
if(firstName)
{
requestContactsString = [requestContactsString stringByAppendingFormat:@"<firstname>%@</firstname>", firstName];
CFRelease(firstName);
firstName = nil;
}
if(lastName)
{
requestContactsString = [requestContactsString stringByAppendingFormat:@"<lastname>%@</lastname>", lastName];
CFRelease(lastName);
lastName = nil;
}
if(email)
{
if(ABMultiValueGetCount(email)>0)
{
CFTypeRef em = ABMultiValueCopyValueAtIndex(email, 0);
requestContactsString = [requestContactsString stringByAppendingFormat:@"<email>%@</email>", em];
CFRelease(em);
}
CFRelease(email);
email = nil;
}
if(phone)
{
if(ABMultiValueGetCount(phone)>0)
{
CFTypeRef ph = ABMultiValueCopyValueAtIndex(phone, 0);
requestContactsString = [requestContactsString stringByAppendingFormat:@"<phone>%@</phone>", ph];
CFRelease(ph);
}
CFRelease(phone);
phone = nil;
}
requestContactsString = [requestContactsString stringByAppendingFormat:@"</item>"];
}
if(allPeople)
{
CFRelease(allPeople);
allPeople = nil;
}
if(addressBook)
{
CFRelease(addressBook);
addressBook = nil;
}
requestContactsString = [requestContactsString stringByAppendingFormat:@"</contacts>"];
NSString *hashedContactsString = [self generateHashedPassword:requestContactsString];
The major inefficiency I can see is the use of
[NSString stringByAppendingFormat]which is creating a newNSStringobject each time it’s called. This means that you have a large number of long auto-releasedNSStringobjects that are no longer being used until the next run loop (unless you are using ARC, in which case the situation is probably better).I think you would make much better use of memory, and get better performance, by making
requestContactsStringanNSMutableStringand using[NSMutableString appendString](reference) instead. This would modify the existing object, allocating more memory to accept the new string.Each append would look like this:
Which still creates a large number of auto-released objects, but they are much smaller.