Reputation: 3667
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];
Upvotes: 1
Views: 556
Reputation: 122458
The major inefficiency I can see is the use of [NSString stringByAppendingFormat]
which is creating a new NSString
object each time it's called. This means that you have a large number of long auto-released NSString
objects 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 requestContactsString
an NSMutableString
and 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:
[requestContactsString appendString:[NSString stringWithFormat:@"<lastname>%@</lastname>", lastName]];
Which still creates a large number of auto-released objects, but they are much smaller.
Upvotes: 3
Reputation:
Use a NSMutableString
and build your XML with the appendFormat:
method. In your loop you are copying the whole string you've assembled so far multiple times.
Upvotes: 1